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!