Ein Lockfile soll ausschließen, dass verschiedene Prozesse oder mehrere Instanzen desselben Skripts gleichzeitig in ein bestimmtes File schreiben, denn das würde sehr wahrscheinlich Datenmüll produzieren. Das scheint nicht besonders schwer: Man wartet bis kein Sperrfile mehr existiert und legt danach ein eigenes an - fertig. Das könnte etwa so aussehen:
while [ -f $lockfile ] ; do sleep 1 done touch $lockfile
Die Sache hat allerdings einen Haken: Wenn das Swapping den Prozess zufällig zu dem Zeitpunkt auslagert, an dem er das "done" verarbeitet, aber das "touch" noch nicht ausgeführt hat, dann existiert für einen konkurrierenden Prozess in der nächsten Zeitscheibe kein Lockfile. Dieser Prozess legt also ein eigenes an. Jetzt kommt der pausierte Prozess zurück und führt das "touch" aus. In der Folge glauben beide Prozesse, sie hätten exklusiv Zugriff auf die Ressource - in Wirklichkeit kommen sie sich aber ins Gehege.
Um eine solche Race Condition zu vermeiden haben die Autoren von Procmail ein nützliches kleines Tool geschaffen, das Bestandteil der meisten Linux-Distributionen ist. Es enthält das Shell-Kommando "lockfile", das Sperrdateien sicher erzeugen kann. Benutzt wird es prinzipiell so:
lockfile important.lock ... <Zugriff auf das gesicherte File> ... rm -f important.lock
Ein etwas ausführlicheres Beispiel sieht auszugsweise so aus:
... if [ -z "$(which lockfile | grep -v '^no ')" ] ; then echo "$0 failed: 'lockfile' utility not found in PATH." >&2 exit 1 fi if [ "$action" = "lock" ] ; then if ! lockfile -1 -r $retries "$1" 2> /dev/null; then echo "$0: Failed: Couldn't create lockfile in time" >&2 exit 1 fi else # action = unlock if [ ! -f "$1" ] ; then echo "$0: Warning: lockfile $1 doesn't exist to unlock" >&2 exit 1 fi rm -f "$1" fi exit 0
Der Name des Lockfiles wurde dem Skript hier als erster Parameter übergeben ($1). Über die Variable $retries lässt sich die Anzahl Wiederholungen einstellen, nach deren Überschreitung das Skript kapituliert. Man kann mit -l (locktimeout) übrigens auch eine zeitliche Grenze für die maximale Lebensdauer eines Locks angeben.