Very simple script to demonstrate the concept:
if [[ -f /a/file ]]
then echo "a copy of script is running."
else touch /a/file
fi
trap 'rm /a/file; exit' 0 1 2 3 15
--
unix programs: niftp (non-interactive recursive ftp), hide (hide command args),
submit (replace nohup), etc from ftp://ftp.mindspring.com/users/mwang/unix-prog
Michael Wang, mw...@ml.com, Merrill Lynch, World Financial Center, 212-449-4414
I normally use a directory as a lock file -- since creating a directory
is usually an atomic operation. In Bourne shell:
mkdir /tmp/locka 2>/dev/null || {
echo Already running
exit
}
trap "rmdir /tmp/lock" 0
... # Do your thing.
Even if you do your damndest to start two or more at the same time,
only one will succeed.
You have a potential race condition. In the time between:
if [[ -f /a/file ]]
and touch /a/file
there is time for another script to:
if [[ -f /a/file ]]
You need an atomic operation that will return an error and set the
semaphore simultaneously. The mkdir command does nicely.
The problem with this, of course, is ensuring that the semaphore
is rmdir'd successfully. Be sure to set plenty of traps:
# block all signals
SIGS=$(echo "for (i=0;i<35;i++)i"|bc)
trap : $SIGS
SEMAPHORE=/var/spool/semaphores/${0##*/}
if mkdir $SEMAPHORE
then
# go to town
trap "[[ -d $SEMAPHORE ]] && rmdir $SEMAPHORE" $SIGS
else
echo "a copy of script is running."
fi
That's probably overkill on the traps and you need to play
around to see what the side effects are (set the trap in a stub
script, send kill).
Note, by trapping on 0 you don't need to place another
rmdir in your code.
Dan Mercer
Opinions expressed herein are my own and may not represent those of my employer.