Some notes on understanding how to use
command has rather complicated usage, with a bunch of options, which
makes it not entirely clear how to use it for shell script locking in various different circumstances. Here
are some notes on this, starting with understanding what it's doing
and the implications of that.
The key to understanding all of
flock(1)'s weird options is to
automatically releases your lock when the last copy of the file
descriptor you locked is closed, and that file descriptors are
shared with child processes.
Given this, we can start with the common basic
flock(1) usage of:
flock -n LOCKFILE SHELL-SCRIPT [ARGS ...]
LOCKFILE, locks it with
flock(2), and then
starts the shell script, which will inherit an open (and locked)
file descriptor for
LOCKFILE. As long as the shell script process
or any sub-process it starts still exists with that file descriptor
open, the lock is held, even if
flock(1) itself is killed for
This is generally what you want; so long as any component of the
shell script and the commands it runs is still running, it's
potentially not safe to start another copy. Only when everything
flock included, is the lock released.
However, this is perhaps not what you want if
flock is used to
start a daemon that doesn't close all of its file descriptors,
because then the daemon will inherit the open (and locked) file
LOCKFILE and the lock will never be released. If
this is the case, you want to start
flock with the
which does not pass the open file descriptor for
LOCKFILE to the
flock winds up running:
flock -n -o LOCKFILE SHELL-SCRIPT [ARGS ...]
Run this way, the only thing holding the lock is
flock exits (for whatever reason), the file descriptor will
be closed and the lock released, even if
SHELL-SCRIPT is still
(Of course, having a daemon inherit an open and locked file descriptor
LOCKFILE is a convenient way to only have one copy of the daemon
running. As long as the first copy is still running, further attempts to
get the lock will fail; if it exits, the lock is released.)
The final usage is that
flock(1) can be directly told the file
descriptor number to lock. In order to be useful, this requires
some shared file descriptor that will live on after
the usual place to get this is by redirecting some file descriptor
of your choice to or from a file for an entire block of a shell
script, like this:
( flock -n 9 || exit 1 ... # locked commands ) 9>/var/lock/mylockfile
This is convenient if you only want to lock some portions of a shell
script or don't want to split a shell script into two, especially
since the first will just be '
flock -n /var/lock/mylockfile
script-part-2'. On the other hand, it is sort of tricky and clever,
perhaps too clever. I'd certainly want to comment it heavily in
any shell script I wrote.
However, you don't necessarily have to go all the way to doing this
if you just want to
flock some stuff that involves shell operations
like redirecting files and so on, because you can use '
to run a shell command line instead of just a program:
flock -n LOCKFILE -c '(command1 | command2 >/some/where) && command3'
This can also get too tricky, of course. There's only so much that's sensible to wedge into a single shell command line, regardless of what's technically possible.
Once you're locking file descriptors, you can also unlock file
descriptors with '
flock -u'. This is probably useful mostly if
you're going to unlock and then re-lock, and that probably wants
you to be using
flock without the '
-n' option for at least the
re-lock. I imagine you could use this in a shell script loop, for
example something like:
( for file in "$@"; do flock 9; big-process "$file"; flock -u 9 more-work ... done ) 9>/var/lock/mylockfile
This would allow
more-work to run in parallel with another
big-process, while not allowing two
to be running at once.
(This feels even more tricky and clever than the basic usage of
flock'ing a file descriptor in a shell '
( ... )' block, so I
suspect I'll never use it.)