To do simple locking in shell scripts, you need an atomic system call that fails if the target already exists, and that is directly exposed in a utility program. Ignoring for a moment what System V did to
ln
, there are two good candidates on modern Unix systems:
link(2)
and
mkdir(2)
.
Mkdir
is actually the better of the two (because you don't have to fiddle around with temporary files), but
ln
is the more common one, probably for two reasons:
- with
mkdiryou can't atomically associate some extra information, like a PID, with the lock. You can put a PID file inside the directory, but there will be a time when it doesn't exist although you have the lock. - there was no
mkdir(2)system call in V7; it was only added in UCB BSD, and didn't make it into System V until fairly late. So for a fair timemkdirwasn't actually suitable for this, and everyone got into the habit of usingln.
General locking with
mkdir
is simple:
mkdir LOCK 2>/dev/null || exit 0 echo running locked rmdir LOCK
Locking with
ln
( ignoring System V ) is somewhat more complicated:
echo $$ >$$ if ln $$ LOCK 2>/dev/null; then echo running locked rm $$ LOCK else rm $$ fi
In both cases you really want a private directory for the locks. If you have to use a shared directory like
/tmp
, I believe the
ln
approach is the only one that can stand up to hostile attacks (provided that you use something like
mktemp
to securely create the temporary file).