Welche Unix-Befehle können als Semaphor / Sperre verwendet werden?

34

Ich möchte mehrere Bash-Shell-Skripte gleichzeitig ausführen. Ich möchte jedoch Rennbedingungen vermeiden. Welche Unix-Befehle sind wirklich atomar, die ich für diesen Zweck verwenden könnte, und wie kann ich sie verwenden?

Larry Wang
quelle
Was machst du, das erfordert parallele Arbeit? Können Sie die Abhängigkeiten nicht so ausdrücken, dass eine Parallele make(1)übernehmen kann? (also a make -j 9wenn du 8 Kerne hast)? Dies hat den zusätzlichen Vorteil, dass Interleaving-Arbeiten mit einer feineren Granularität ausgeführt werden.
Vonbrand

Antworten:

30

Wenn lockfilees nicht auf Ihrem System installiert ist, mkdirerledigt es die Arbeit: Es ist eine atomare Operation und es schlägt fehl, wenn das Verzeichnis bereits vorhanden ist (solange Sie den -pBefehlszeilenschalter nicht hinzufügen ).

create_lock_or_wait () {
  path="$1"
  wait_time="${2:-10}"
  while true; do
        if mkdir "${path}.lock.d"; then
           break;
        fi
        sleep $wait_time
  done
}

remove_lock () {
  path="$1"
  rmdir "${path}.lock.d"
}
Riccardo Murri
quelle
26

flock(1)

#!/bin/bash

# Makes sure we exit if flock fails.
set -e

(
  # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
  flock -x -w 10 200

  # Do stuff

) 200>/var/lock/.myscript.exclusivelock

Dadurch wird sichergestellt, dass der Code zwischen "(" und ")" jeweils nur von einem Prozess ausgeführt wird und der Prozess zu lange auf eine Sperre wartet.

Alex B
quelle
Netter, wusste nichts davon. Es ist jedoch anscheinend Linux-spezifisch ...
Riccardo Murri
1
@Riccardo hat FreeBSD einen ähnlichen Befehl: lockf(1).
Alex B
lockf(1)funktioniert jedoch nicht so wie in diesem Beispiel. Eine Dateideskriptornummer kann nicht als Argument verwendet werden.
Charley
11

lockfile (1) sieht aus wie ein guter Kandidat, obwohl es Teil des procmail- Pakets ist, das Sie möglicherweise noch nicht auf Ihrem Computer installiert haben. Es ist ein beliebtes Paket, das für Ihr System gepackt werden sollte, wenn es noch nicht installiert ist. Drei der vier von mir überprüften Systeme haben es und das andere hat es zur Verfügung.

Die Benutzung ist einfach:

#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`

echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
    # Do protected stuff here
    echo Doing protected stuff...

    # Then, afterward, clean up so another instance of this script can run
    rm -f $LOCKFILE
else
    echo "Failed to acquire lock!  lockfile(1) returned $?"
    exit 1
fi

Die Optionen, die ich angegeben habe, lassen es bis zu 15 Sekunden lang einmal pro Sekunde wiederholen. Löschen Sie das Flag "-r", wenn Sie möchten, dass es für immer wartet.

Warren Young
quelle
2
Nur als Referenz - die Manpage: linux.die.net/man/1/lockfile . :)
Lucas Jones
Beachten Sie, dass (laut Manpage) "Sobald eine Datei gesperrt ist, muss die Sperre mindestens alle fünf Minuten berührt werden, da sonst die Sperre als veraltet angesehen wird und nachfolgende Sperrversuche erfolgreich sind."
Jay
6

Der Systemaufruf mkdir()ist bei POSIX-Dateisystemen atomar. Verwenden Sie den mkdirBefehl also so, dass genau ein Aufruf mkdir()erforderlich ist, um Ihren Zweck zu erreichen. (IOW, nicht benutzen mkdir -p). Das entsprechende Entsperren ist rmdirnatürlich.

Vorsichtsmaßnahme: mkdir()Möglicherweise sind Netzwerk-Dateisysteme nicht atomar.

Hari
quelle
ist rmdiralso auch atom?
Alexej Magura
3

Vielleicht wird der Befehl lockfile das tun, was Sie brauchen.

lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
jacksonh
quelle
Dies scheint die falsche Datei zu löschen.
Benjamin W.
1

Wenn Sie nur unter Unix arbeiten, verwenden Sie fifos. Sie können Arbeitsdatensätze in das Fifo schreiben und Prozesse aus dieser Datei lesen lassen, und Ihre Leser blockieren die Fifos.

Sperrdateien sind in Ordnung, aber für das, was Sie beschreiben, würde ich mit Fifos gehen

Chris
quelle
1
Könnten Sie näher erläutern, wie Fifos Ihrer Meinung nach Rennbedingungen vorbeugen können?
G-Man sagt, Monica werde