Could I trap a 5-minute signal inside my script? I imagine something like this,
function dosomething {
echo "It's been 5 minutes."
}
trap dosomething SIGNAL-EVERY-5-MINUTES
while true
do
sleep 10
done
Note that this example doesn't have sense. It's just to ask if it's possible to trap something every x time.
EDIT: Based on @vinc17 answer, I've noticed that sleep
command from the main shell isn't interrupted by USR1
signal, and that's what I want to do.
#!/bin/bash
time=10
(
set -e
while true
do
sleep 30
# Since this is run as a subshell (instead of an external command),
# the parent pid is $$, not $PPID.
kill -USR1 $$
done
) &
finish() {
kill $!
echo "Closing."
exit 0
}
changetime() {
echo "Signal USR1 received."
time=$(( $RANDOM % 8 + 1))
}
trap changetime USR1
trap finish SIGINT
while true
do
echo "before sleep"
sleep $time
echo "after sleep"
done
outputs,
before sleep
Signal USR1 received.
after sleep
before sleep
Signal USR1 received.
after sleep
before sleep
Signal USR1 received.
Closing.
EDIT2: I've edited the above example, resulting in the same output, but adds one more difficulty: The sleep time is changed by the USR1
trap function. So now, every 30 seconds a random time between 1 and 8 is chosen. SO, I need to kill sleep
from the main script when signal changes its time. I insist on that it has no sense, but I need to know if it is possible.
Best Answer
You can run a process that will send a signal (e.g.
SIGALRM
) to the shell script every x time, and use a trap for this signal. This process could be a script doing something like:if started by the main shell script.
The main shell script should kill this process when it is no longer needed, and/or the process should terminate when the pid no longer exists (however there's a race condition on that).
(EDITED) Note: If your main shell script uses the
sleep
command, it may badly interact with theALRM
signal ifsleep
is a builtin andsleep(3)
is implemented withalarm(2)
. The POSIX description of thesleep
shell utility also says in its rationale: "The exit status is allowed to be zero when sleep is interrupted by the SIGALRM signal because most implementations of this utility rely on the arrival of that signal to notify them that the requested finishing time has been successfully attained. Such implementations thus do not distinguish this situation from the successful completion case. Other implementations are allowed to catch the signal and go back to sleep until the requested time expires or to provide the normal signal termination procedures." To avoid potential issues with some implementations, you can useSIGUSR1
orSIGUSR2
instead ofSIGALRM
.Here's an example using a subshell. To make the behavior easier to see, I've replaced the 5-minute period (
sleep 300
) by a 5-second period (sleep 5
).The script can be interrupted with Ctrl-C. It doesn't kill the subshell when this happens, but if the pid isn't reused, the subshell terminates automatically after no more than the period (here, 5 seconds) because the
kill
command fails (kill: No such process
).