Consider the following script:
#!/bin/bash
set -o pipefail
set -o history
trapper() {
func="$1" ; shift
for sig ; do
trap "$func $sig" "$sig"
done
}
err_handler () {
case $2 in
INT)
stop_received=1
;;
TSTP)
;;
ERR)
if [[ $2 != "INT" ]]; then # for some reason, ERR gets triggered on SIGINT
code=$?
if [ $code -ne 0 ]; then
echo "Failed on line $1"
echo "$BASH_COMMAND returned $?"
echo "Content of variables at the time of failure:"
echo "$(set -o posix; set)"
exit 1
fi
fi
;;
esac
}
main() {
ping -c 5 www.google.com # this is a test to see if INT interrupts main()
# do a bunch of stuff, I mean a real bunch of stuff, like check some
# files, do some processing, connect to a database,
# do more processing, move some files around, you get the drift
}
exec > >(tee -a my.log)
exec 2>&1
trapper 'err_handler $LINENO' INT TSTP ERR
while main
do
if [[ "$stop_received" == "1" ]]; then
break
fi
setsid sleep 2 & wait
done
trap ERR
What I am trying to accomplish is to run the script in an infinite loop until either the function main() returns some non zero value, i.e. some error occurred, or SIGINT is received.
However, I don't want SIGINT to stop main() from executing, in other words, if the script receives a SIGINT, it should wait for main() to finish, then exit nicely. But when I hit CTRL+C, I can see that ping is interrupted. At the moment I commented out everything under main() just to see if this works. Since ping gets interrupted, I am assuming other commands under main() would also get interrupted. When ping is interrupted, the processing jumps to the line where I check if $stop_received=1 and then the loop breaks and the script quits. If I replace the break with just an echo, then the script just continues on to the next iteration of the while main loop.
How can I stop SIGINT from interrupting the currently running command(s)? Since my script does a bunch of stuff, including DML statements in a database, interrupting main() would cause lot of grief.
Secondly, the script does not trap ctrl+z either. Or rather, the script just gets stuck on ctrl+z requiring a kill pid to terminate. I assumed that sleep being a child of bash as opposed to the script itself, ctrl+z would cause the script to pause, leaving sleep in limbo land. Hence the setsid and wait on sleep, but it still hangs.
thanks.