Wandering Thoughts archives

2007-02-11

How to do locking in shell scripts

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

unix/ShellScriptLocking written at 23:15:38; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.