How to do locking in shell scripts

February 11, 2007

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:

  1. with mkdir you 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.
  2. 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 time mkdir wasn't actually suitable for this, and everyone got into the habit of using ln.

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
  rm $$

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).

Written on 11 February 2007.
« Weekly spam summary on February 10th, 2007
Why thin clients are doomed (part 2) »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Feb 11 23:15:38 2007
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.