A lockfile can be used when a particular program might be run more than once at the same time and you need to be sure that only one instance of the program can do something (modify some file, access a printer, etc.). To really do this right, the program needs to both test for the lockfile and create it (if it doesn't exist) in one atomic operation. If the test-and-set operation isn't atomic — for instance, if a program tests for the lock file in one command and then creates the lock file in the next command — there's a chance that another user's program could do its test at the precise moment between the first program's (non-atomic) test and set operations. The technique in this article lets you make a lockfile atomically from a shell script.
touch /tmp/xxx
ln -s /tmp/xxx /tmp/lockfile 2>/dev/null
ret=$?
rm /tmp/xxx
if [ $ret -ne 0 ];then
echo lockfile already exists
exit 1
else
echo success
fi
Race conditions:
It's worth pointing out that there is a slight race condition in the above lock example between the time we test for the lockfile and the time we create it. A possible solution to this is to use IO redirection and bash's noclobber mode, which won't redirect to an existing file. We can use something similar to:
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null;
then
trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
critical-section
rm -f "$lockfile"
trap - INT TERM EXIT
else
echo "Failed to acquire lockfile: $lockfile."
echo "Held by $(cat $lockfile)"
fi
Another solution: Thanks Power Tools book...
LOCKFILE="/tmp/lockfile"
ACTION_WAIT="0"
MAX_ACTION_WAIT="60"
trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT
until (umask 222; echo "$$" > "$LOCKFILE") 2>/dev/null
do
if [ "$ACTION_WAIT" -ge "$MAX_ACTION_WAIT" ]; then
echo "expiring the lock"
rm -f "$LOCKFILE"
return 1
else
echo "Waiting for current ACTION to finish"
ACTION_WAIT=$(($ACTION_WAIT + 1))
fi
sleep 1
done
No comments:
Post a Comment