ADMIN-Tipp: Locks für die Shell

Jede Woche erscheint in unserem Newsletter ein neuer ADMIN-Tipp. Eine Sammlung aller Tipps finden Sie im Archiv der ADMIN-Tipps.

Jedes Shellskript, das auf ein gemeinsam benutztes File zugreift, sollte einen Locking-Mechanismus implementieren. Aber Vorsicht: Die einfachsten Ideen funktionieren schlecht.

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.

05.03.2013

Ähnliche Artikel

comments powered by Disqus

Artikel der Woche

Systeme mit Vamigru verwalten

Auch wer nur kleine Flotten von Linux-Servern verwaltet, freut sich über Werkzeuge, die ihm diese Arbeit erleichtern. Vamigru tritt mit diesem Versprechen an. Wir verraten, was es leistet und wie Sie es in der eigenen Umgebung in Betrieb nehmen. (mehr)
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Container

Wie setzen Sie Container ein?

  • Gar nicht
  • Docker standalone
  • Docker mit Kubernetes
  • Docker mit Swarm
  • Docker mit anderem Management
  • LXC/LXD
  • Rocket
  • CRI-O auf Kubernetes
  • Container auf vSphere
  • Andere (siehe Kommentare auf der Ergebnisseite)

Google+

Ausgabe /2018

Microsite