Assume that you want to create a script that will run forever unless ctrl+c is pressed.. well as you might already know is that you can do this without any effort, you can press any time ctrl+c and the script will exit, but what it does not do is that isn't exit the script gracefully, this means that the script doesn't do any cleanup that might needed, it is just exits, in this article i will show you how to handle signals like ctrl+c (SIGINT) and perform some cleanup functionality after ctrl+c is pressed.
Loop forever!
in this basic example we have a simple bash script that enters a loop that will never exit unless ctrl+c is pressed, in this loop test.tmp is created and deleted every one second, i ctrl+c is pressed there are many chances that test.tmp might not be deleted, how we can ensure that test.tmp will be deleted even after ctrl+c is pressed?
#!/bin/bash
while true; do
touch test.tmp
sleep 1
echo "Running..."
rm -f test.tmp
done
Its a trap!
Bash has the trap command, the trap command allows catching signals (ctrl+c is the SIGINT signal) and execute a command upon capturing, the trap syntax is the following
trap function_command_to_execute SIGNAL
Quite simple and cool! right? let's adapt our original script with trap!
#!/bin/bash
cleanup(){
echo ""
echo "CTRL+C pressed, clean up things before exiting..."
rm -rf touch.tmp 2>/dev/null
exit 1
}
# Trap the SIGINT signal (Ctrl+C)
trap cleanup SIGINT
while true; do
touch test.tmp
sleep 1
echo "Running..."
rm -f test.tmp
done
Running our script and pressing ctrl+c generates the following results:
./hello.sh
Running...
Running...
Running...
^C
CTRL+C pressed, clean up things before exiting...
the signal generated from pressing ctrl+c is caught and the cleanup function is executed! great! you might have some questions now
why you used echo twice?
echo ""
echo "CTRL+C pressed, clean up things before exiting..."
The reason is that pressing ctrl+c without entering a newline will mess up the output
❯ ./hello.sh
Running...
Running...
Running...
Running...
^CCTRL+C pressed, clean up things before exiting...
Why you redirected stderr to /dev/null
?
rm -rf touch.tmp 2>/dev/null
/dev/null
is a special device name that acts as a black hole! everything you throw there disappears! this way if the file that we try to delete has been already deleted will not show an error in the screen which might confuse the user without reason!
Why you exited the script with exit 1?
exit codes are very useful! an exit code of 0 indicates that the program / script completed as supposed to, anything else could be indicate that exited by an abnormal way or because of an error. This makes troubleshooting easier but also allows control flow, we can read the exit status of a script or a program by using the $? variable.. this allows bash scripts to decide what to do if another script or program exited abnormaly
❯ ./hello.sh
Running...
Running...
Running...
^C
CTRL+C pressed, clean up things before exiting...
❯
❯ echo $?
1
Conclusion
Knowing to handle signals like pressing ctrl+c is very handy since allows you to do cleanup jobs before your script exits! did you liked this article? leave your comments!