Often when writing scripts to run on a schedule, we want to avoid the same script running multiple instances at once, there is a frequently used pattern of handling this:
if [ -f /some/lock/file ]; then exit 1 fi touch /some/lock/file # our actual script... rm -f /some/lock/file
Which just says if a lock file exists, stop doing what you're doing because the last script hasn't terminated yet. Simple and effective, but somewhat ugly.
coreutils package contains a utility called
flock which can handle locks for us.
So typically with the above script a crontab would just look like:
0 * * * * /myscript.sh
Instead we can remove that ugly lock file boilerplate from the script, and change our crontab to use
0 * * * * flock /some/lock/file --command '/myscript.sh'
This functions a little bit differently however, because
By default, if the lock cannot be immediately acquired, flock waits until the lock is available.
We can actually change this to immediately fail if the lock can't be obtained using the
0 * * * * flock --nonblock /some/lock/file --command '/myscript.sh'
Benefits to using an
- Leaves the logic of locking out of your script
- It works in the event of a script failing in between the
touch, and the
- This actually does more than just create/delete a file, in fact it never deletes the lock file. It just checks if any process is currently making use of the lock file.
flockdoes much more than this, including trying to acquire a lock for a defined period of time before failing, properly handling child processes with the
--closeflag, and more.