Traps: make your bash scripts more robust

Surfing the national network I came across a interesting article (which I bring here textually because it is masterfully explained) where its author shows us how to make our Bash scripts more robust using Traps.

Make your bash scripts more robust with traps

Imagine that you have a bash script that runs every day every six hours and that at some point it fails or that same script runs twice simultaneously. These two situations are quite uncomfortable as they require human intervention to be corrected or at certain times they cannot be addressed, leaving the system in an inconsistent state. The solution to this, among others, is to use traps.

Traps is a simple and effective way to control the output of bash scripts. Let's go back to the same initial situation, if the script is stopped manually, for example with ctrl-c, it is interrupted returning the output signal

INT

and if it ends with

kill

then the output would be

TERM.

All possible exit codes can be viewed with

kill -l

however the most used are precisely

INT, TERM, EXIT

If the script consists, for example, of file synchronization with

rsync

The most sensible thing is to rely on a lock file that does not allow the script to run simultaneously:

LOCK = "/ var / run / rsync.lock" if [! -e $ LOCK]; then touch $ LOCK rsync -avz foo bar rm $ LOCK else echo "rsync is already running" fi

In plain Spanish, the previous script checks if the lock file exists and if it does not exist, it creates it and later executes the corresponding command, finally deleting the lock file. If the file exists, the script simply sends a message to the user indicating that the command is already running.

However, when there is a problematic situation it could happen that the lock file is not eliminated, ruining unwanted effects. The solution is very simple:

LOCK = "/ var / run / rsync.lock" if [! -e $ LOCK]; then trap "rm -f $ LOCK; exit" INT TERM EXIT touch $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM EXIT else echo "rsync is already running" fi

The particularity of this solution is that the command is enclosed in a trap, so that when a signal is received

INT, TERM, EXIT

the script stops and clears the lock file.

It is worth saying that there could be a competition situation in the script above between the time the lock file is verified and the time it is created. A possible solution would be to use a redirect and bash's noclobber mode which doesn't redirect to an existing file:

LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; then trap 'rm -f "$ LOCK"; exit $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT else echo "rsync is already running: $ (cat $ LCK)" fi

The peculiarity of the latter is that it is used as I had already said, the noclobber mode and that the lock file contains the PID of the process that is being executed.

It is also worth mentioning that there are other solutions such as

flock

o

solo

however in this post I wanted to share the solutions with bash's own resources. You can learn a little more about Traps with this excellent guide.


Leave a Comment

Your email address will not be published. Required fields are marked with *

*

*

  1. Responsible for the data: Miguel Ángel Gatón
  2. Purpose of the data: Control SPAM, comment management.
  3. Legitimation: Your consent
  4. Communication of the data: The data will not be communicated to third parties except by legal obligation.
  5. Data storage: Database hosted by Occentus Networks (EU)
  6. Rights: At any time you can limit, recover and delete your information.

  1.   Raphael Castro said

    Great! Thanks for sharing.

  2.   nx said

    Nice article, just change 'echo "rsync is already running: $ (cat $ LCK)"' to 'echo "rsync is already running: $ (cat $ LOCK)"'

    regards

  3.   dglangos said

    A very interesting article, yes sir! This I keep.

  4.   Joaquin said

    It is a very useful command to keep in mind. I used it in a script that I published in a post, to delete some files that the script created when it was stopped.

  5.   DaniFP said

    Very interesting, yes sir.