Springe zum Inhalt

Bash-Scripte gegen gleichzeitiges Ausführen absichern

Oft darf von einem Bash Script nur eine Instanz laufen. Beispiele sind ein Backup oder ein Datei-Transfers, welche bei gleichzeitigem Lauf der selben Scripte evtl. nicht korrekt durchgeführt würden. Mit einfachen bash-Mitteln lässt sich dies jedoch verhindern.

Ganz einfach könnte man auf das Vorhandensein einer Datei testen und sie anlegen, falls sie nicht existiert. Allerdings hätte man sich damit auch eine sogenannte RaceCondition geschaffen, der Vorgang zwischen Test und Anlegen ist nicht atomar. Ein nicht funktionierendes Beispiel:

Nehmen wir an, zwei Instanzen eines Skripts mit diesem Schnipsel kommen gleichzeitig an die Stelle des Tests auf das Vorhandensein des Lockfiles. Beide finden das Lockfile nicht und werden weiter ausgeführt!

Atomar hingegen ist das Anlegen von Verzeichnissen. mkdir legt ein Verzeichnis an und testet gleichzeitig, ob es bereits vorhanden ist. Mit folgendem Schnipsel am Scriptanfang kann ein gleichzeitiges Ausführen des selben Scripts verhindert werden:

trap sorgt dafür, dass bei Beendigung des Scripts das Lock-Verzeichnis wieder entfernt wird.

Eins sei noch erwähnt: wenn der Prozess in dem das Script läuft, also die bash, mit "kill -9" abgewürgt wird, wird der Befehl hinter trap nicht mehr ausgeführt. Das Lock-Verzeichnis muss dann manuell entfernt werden.

Update vom 16.02.2016: Hinweis auf RaceCondition und Lösung mit mkdir hinzugefügt.

2 Gedanken zu „Bash-Scripte gegen gleichzeitiges Ausführen absichern

    1. Jens Tautenhahn

      Leider hat flock in meiner Version einen unschönen Bug, der das "Boilerplate"-Beispiel aus der Man-Page von flock unbrauchbar macht.

      Das wäre sehr elegant, führt aber in util-linux 2.20.1 nur zur Fehlermeldung: "Text file busy" bzw. "Das Programm kann nicht ausgeführt oder verändert werden (busy)". Abhilfe schafft "chmod -w", was aber nicht im Sinne des Erfinders sein kann.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.