Re: File-Locking in Shellscripten auf NFS

Autor: Markus Hochholdinger <Markus_at_hochholdinger.net>
Datum: Thu, 9 Dec 2010 10:32:02 +0100
Hi Raphael,

Am 08.12.2010 um 21:19 Uhr schrieb Raphael Eiselstein <rabe_at_uugrn.org>:
> für manche Anwendungsfälle möchte man z.B. vermeiden, dass ein Script
> mehrfach parallel ausgeführt wird, etwa per cron, wenn die Ausführung
> aus irgendwelchen Gründen länger dauert als die Periode in cron
> eingestellt ist.

dafür ist auch manchmal "lockfile" geeignet, was bei mir in dem 
Paket "procmail" dabei ist.


> Der IMHO übliche weg ist ein PID-File zu schreiben, welches die
> Prozess-ID des laufenden Prozesses enthält. Wird das Script (oder
> Programm) dann parallel nochmal gestartet, kann man anhand des
> vorhandenen PID-Files bzw. nach Überprüfung der darin enthaltenen PID
> herausfinden, ob eine weitere Instanz bereits läuft und entsprechend
> darauf reagieren, zB nicht nochmal neu starten.

Das ist natürlich der Königsweg auf EINEM System.


> Wie würde man so ewtas implementieren, wenn es mehrere Systeme gibt, die
> ein bestimmtes Programm periodisch ausführen aber sichergestellt werden
> soll, dass immer nur eins gleichzeitig ausgeführt wird?

Evtl. sind hierbei PID-Files nichtmehr geeigent, da ja mehrere Systeme daran 
beteiligt sind. Ohne die anderen Systeme "fragen" zu müssen sehe ich nur eine 
Möglichkeit:
Während "Programm" läuft das PID-File bzw. Lock-File regelmäßig zu 
aktualisieren (touch file) und anhand vom timstamp der Datei entscheiden 
ob "Programm" noch läuft oder nicht.


> Man könnte hier zwar auch ein PID-File auf ein gemeinsames NFS-Volume
> schreiben. Das ließe sich dann aber nicht prüfen, d.h. ein vorhandenes
> PID-File allein genügt nicht um zu überprüfen, ob die darin enthaltene
> Prozess-ID noch gültig ist (der Prozess läuft ja möglicherweise auf
> einem fremden System).
> Kann man auf NFS eine Datei derart locken, dass der Lock entfernt wird,
> falls der "sperrende" Prozess abgestürzt ist?

Soweit ich weiß geht das nicht.


> Und wenn ja, wie implementiert man soetwas in einem Shellscript oder mit
> welchem Standardtool kann man das tun? Wie erkennt man nicht nur, dass
> ein anderer Prozess gestartet ist sondern dass diese PID auch noch aktiv
> ist?
> Ein Workaround wäre, auf jedem der beteiligten Systeme einen
> unabhängigen Cronjob zu haben, der alle PID-Files sucht und prüft, ob
> der entsprechende (lokale) Prozess noch aktiv ist.
> Dabei müsste im PID-File allerdings auch der Hostname enthalten sein,
> sonst würde der Garbage-Collector-Job auf Host A ein PID-File wegräumen,
> welches von Host-B aus geschrieben wurde.

hier würde ich aber aufpassen, dass es nicht zu kompliziert wird. Wer soll 
soetwas betreuen? Wenn da mal etwas nicht wie erwartet funktioniert wird es 
schwierig herauszufinden wieso etwas nicht geht.


> Nachteil dieser Methode: stirbt das ganze System (zB Host B), würde das
> Lock-/PID-File auf dem NFS liegen bleiben und nicht weggeräumt werden, da
> ja auch der Garbage Collector-Job nicht mehr laufen würde.
> Man könnte als Workaround^2 dafür sorgen, dass alle Hosts sich
> gegenseitig den Garbage Collector Job überwachen. Dazu müsse der
> GC-Prozess auf jedem System ein Statusfile updaten und jeweils alle
> GC-Monitoring-Prozesse würden anhand des Dateialters herausfinden, wenn
> ein GC-Job länger als erlaubt nicht mehr gelaufen ist und damit den
> jeweiligen Host für tot erklären und entsprechend auch alle PID-Files
> des für tot erklärten Host automatisch wegräumen.
> Diesen Workaround und Workaround^2 halte ich aber insgesamt für zu
> fragil als dass ich das als sinnvolle Lösung ansehen würde.
> Ein anderer Workaround wäre, zB per xinetd einen Service anzubieten, der
> per einfachem TCP-Connect mit PID als Eingabe mit der Ausgabe "running",
> "stopped", ... den jeweilgen Prozess-Status (sofern vorhanden) ausgibt.
> Damit könnten dann andere Hosts im Netz auch fremde PID-Files
> verifizieren und ggf. für ungültig erklären.
> Das einzige, was in diesem Setup als "hochverfügbar" angesehen werden
> kann ist der NFS-Server, alle NFS-Clients sind einfache Systeme die
> unabhängig voneinander funktionieren müssen, d.h. es darf kein anderes
> "zentrales System" geben.
> Gibt es eine *einfache* Lösung basierend auf NFS?

Wie oben geschrieben würde ich das "Lock-File" auf dem nfs-Server 
während "Programm" ausgeführt wird aktualisieren. In der Bash würde ich das 
wie folgt machen:

INTERVAL="10"
if [ -e /nfs/lockfile ] \
&& [ "$(($(date +%s)-2*$INTERVAL))" -gt "$(date -r /nfs/lockfile +%s)" ]
then
	echo "already running"
else
	touch /nfs/lockfile
	program &
	PID="$!"
	while [ -d "/proc/$PID" ]
	do
		touch /nfs/lockfile
		sleep $INTERVAL
	done
	wait $PID
fi


-- 
Gruß
                                                          \|/
       eMHa                                              (o o)
------------------------------------------------------oOO--U--OOo--
 Markus Hochholdinger
 e-mail  mailto:Markus_at_Hochholdinger.net             .oooO
 www     http://www.hochholdinger.net                (   )   Oooo.
------------------------------------------------------\ (----(   )-
Ich will die Welt verändern,                           \_)    ) /
aber Gott gibt mir den Quelltext nicht!                      (_/


-- 
UUGRN e.V. http://www.uugrn.org/
http://mailman.uugrn.org/mailman/listinfo/uugrn
Wiki: https://wiki.uugrn.org/UUGRN:Mailingliste
Archiv: http://lists.uugrn.org/

Empfangen am 09.12.2010

Dieses Archiv wurde generiert von hypermail 2.2.0 : 09.12.2010 CET