« Security Theatre of the Absurd, part 2 | Main | MySQL resiliency after a crash and relay log files »

useful bash MUTEX code

Problem: you have a script that runs periodically (like from cron) and sometimes the time to complete is longer than the time in between invocations. You end up with multiple scripts running one on top of the other, and if the scripts are at all CPU-intensive, you can bring the machine grinding to a halt.

Solution: use a MUTEX (mutual exclusion) to prevent scripts from starting if one is active. Also use a timer in case one script terminates and doesn't clean up its Ps and Vs.

bash code:


  1. # add in the mutex code
  2. # we need to figure out how to NOT run too frequently, so we don't stomp
  3. # on each other.
  4. # (c) Jerry B. Altzman/3 Phase Computing.
  5. # Permission is granted to use this code but no warranty is implied whatsoever
  6. # requires gnu date
  7. MUTEX=/tmp/MUTEX`basename ${0}`
  8. NOW=`date '+%s'` # seconds since the epoch

  9. # if the mutex exists, see how old it is. If it's too old,
  10. # delete it, and start again.
  11. if [ -f $MUTEX ]; then
  12.   THEN=`cat $MUTEX`
  13.   DELTA=$((NOW-THEN))
  14.   if [ $DELTA -gt 3600 ]; then # too long
  15.     rm $MUTEX
  16.     pkill -9 $0 # will probably kill this one too
  17.   else
  18.     exit 0 # MUTEX is there and relatively new
  19.   fi
  20. else # MUTEX file is not there
  21.   date '+%s' > $MUTEX
  22. fi

  23. trap "rm $MUTEX" 0 1 2 15

The comments are pretty self-explanatory, but just in case, the idea of the code is thus:
Line 7: Define a file that will be the MUTEX for this program. It is unique to this program but shared across all invocations.
Lines 12-14: Check to see if the MUTEX exists. If it does, examine its contents—the contents are the time of the last invocation. If the time is “not too long ago” (I have it set here as one hour, but you can change that depending on your preferences.)
Lines 15-17: If the MUTEX exists, and is “old”, then delete the MUTEX file, and kill off any processes with our name to clean up any “hung” processes (and the next periodic run will start afresh).
Lines 18-20: If we are here, the MUTEX isn’t that old, so we just exit and wait for the next invocation.
Lines 21-23: Otherwise, there is no MUTEX here—either the old process exited normally or we cleared out a hung processes. In any case, create a new MUTEX with the current time.
Line 25: This “trap” statement is a bash directed that says “if this script terminates with exit codes 0, 1, 2, or 15, then perform the operation listed” which, in this case, is to clean up the MUTEX itself.

TrackBack

TrackBack URL for this entry:
http://www.jbaltz.com/mt/mt-tb.cgi/46

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)