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:
LOCKFILE=/var/lock/test.lock
[[ -f $LOCKFILE ]] && exit 1
> $LOCKFILE
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:
LOCK=/var/lock/mylock
if ! mkdir $LOCK 2>/dev/null; then
echo Already running or stale lock exists. >&2
exit 1
fi
trap -- "rmdir $LOCK" EXIT
# do work
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.