I am writing a bash wrapper for an application. This wrapper is responsible for changing the user, running the software and logging its output. I also want it to propagate the SIGINT signal.
Here is my code so far :
#!/bin/bash
set -e; set -u
function child_of {
ps --ppid $1 -o "pid" --no-headers | head -n1
}
function handle_int {
echo "Received SIGINT"
kill -int $(child_of $SU_PID)
}
su myuser -p -c "bash /opt/loop.sh 2>&1 | tee -i >(logger -t mytag)" &
SU_PID=$!
trap "handle_int" SIGINT
wait $SU_PID
echo "This is the end."
My problem is that when I send a SIGINT to this wrapper, handle_int
gets called but then the script is over, while I want it to continue to wait for $SU_PID
.
Is there a way to catch the int signal, do something and then prevent the script from terminating ?
How do I disable Control-C? You need to use the trap command which can enable or disable keyboard keys such as Crtl-C. SIGINT is Crtl-C and it is represented using number 2. Signal names are case insensitive and the SIG prefix is optional.
If you are executing a Bash script in your terminal and need to stop it before it exits on its own, you can use the Ctrl + C combination on your keyboard.
SIGINT is the signal sent when we press Ctrl+C. The default action is to terminate the process. However, some programs override this action and handle it differently. One common example is the bash interpreter.
If you want to exit the loop instead of exiting the script, use a break command instead of an exit. #!/bin/bash while true do if [ `date +%H` -ge 17 ]; then break # exit loop fi echo keep running ~/bin/process_data done … run other commands here …
You have a gotcha: after Ctrl-C, "This is the end." is expected but it never comes because the script has exited prematurely. The reason is wait
has (unexpectedly) returned non-zero while running under set -e
.
According to "man bash":
If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.
You should wrap your wait
call in set +e
so that your program can continue running after handling a trapped signal while waiting for an asynchronous command.
Like this:
# wait function that handles trapped signal on asynchronous commands.
function safe_async_wait {
set +e
wait $1 # returns >128 on asynchronous commands
set -e
}
#...
safe_async_wait $SU_PID
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With