2016-05-23 7 views
0

In 'kornshell' gibt `basename $ 0` mir den Namen des aktuellen Skripts.So implementieren Sie Singleton in Shell-Skript

Wie würde ich $$ oder $ PPID ausnutzen, um das Singleton-Muster von nur einem Skript mit dem Namen `Basisname $ 0` zu implementieren, das von irgendeinem Benutzer auf diesem Server ausgeführt wird?

Dies zeigt mir alle laufenden Prozesse, die den Namen des aktuell laufenden Skripts haben.

Ich brauche ein Skript, das abbrechen kann, wenn ein Thread, der nicht $$ ist, das Skript namens 'Basisname $ 0' ausführt.

+1

Es scheint mir, dass Sie ein Problem haben, und Sie haben viel zu früh eine Lösung für dieses Problem gewählt. Welches Problem versuchen Sie * eigentlich * zu lösen? –

+0

'ps' ist für diese Rolle ungeeignet: Es bietet keine Atomizitäts- oder Gleichzeitigkeitsgarantien; Sein Ergebnis ist nicht garantiert, um einen bestimmten Zeitpunkt darzustellen. Ich finde mich in einer ziemlich überwältigenden Übereinstimmung mit Philip. –

+0

@Goahnary Sie können dies übrigens von Interesse finden, wenn Ihr Problem durch die Instanz Ihres Skripts verursacht wird * Lesen * Ihres Counters überlappend mit einer anderen Instanz des Scripts * Schreiben * des Counters. Beachten Sie, dass "echo foo> bar" nicht atomar ist - es schneidet zuerst "bar" ab, um eine leere Datei zu sein, bevor * foo hinein geschrieben wird; Für Ihren numerischen Zähler würde dies so aussehen, als würde er auf 0 zurücksetzen, bis/sofern Sie keinen Mutex implementieren, um sicherzustellen, dass immer nur ein Job ausgeführt wird. (Wenn der Server kürzlich länger gebraucht hat, um zu antworten, würde das erklären, warum Sie erst kürzlich Bugs gesehen haben). –

Antwort

1

Um einen rennfreien Mutex zu bieten, ist flock Ihr Freund. Wenn Sie nicht unter Linux sind - wo es provided by util-linux ist - ist eine portable version verfügbar.

Wenn Sie wirklich wollen, dass es auf das gesamte System angewendet wird, indem Sie Benutzerkonten kreuzen, benötigen Sie ein Verzeichnis für Ihre Sperren, in dem alle Benutzer Dateien erstellen können, und Sie müssen sicherstellen, dass alle Benutzer kann auf deine Lockfiles schreiben.

Angenommen, Sie haben das flock Dienstprogramm, jedes Programm, das in diesem Protokoll teilnehmen möchte, kann sich wie folgt verhalten:

#!/bin/ksh 

umask 000     # allow all users to access the file we're about to create 
exec 9>"/tmp/${0##*/}.lck" # open lockfile on FD 9, based on basename of argv[0] 
umask 022     # move back to more restrictive file permissions 
flock -x -n 9 || exit  # grab that lock, or exit the script early 

# continue 

Ein wichtiger Hinweis: nicht versuchen Sie Lock-Dateien zu löschen, wenn Ihr Skript beendet. Wenn Sie sich in einem Zustand befinden, in dem jemand anderes aktiv versucht, eine Sperre zu greifen, haben sie bereits einen Dateideskriptor für diese vorhandene Datei; Wenn Sie die Datei löschen, während sie einen Griff haben, haben Sie nur ein Rennen sichergestellt, bei dem das Programm denken kann, dass es die Sperre hält, während jemand anderes eine neue Datei unter demselben Namen erstellt und diese sperrt.

+0

Es gibt keine Atomizität zwischen Ihren Befehlen und daher keine Garantie. Ich glaube nicht, dass das, was gefragt wird, tatsächlich so möglich ist, wie er es möchte. – bodangly

+0

@Bodangly, der Schlüssel hier ist, dass, sobald die Flock ausführbare ruft die 'Flock' Syscall, keine andere' Flock (LOCK_EX) 'auf einem anderen Datei-Deskriptor für die gleiche Inode wird erfolgreich, bis dass FD mit geschlossen oder entsperrt ist 'Herde (LOCK_UN)'. Da das Shell-Skript den Dateideskriptor für den Rest seiner Ausführung offen hält, bedeutet dies, dass nichts anderes über die Zeile "flock -x -n 9" hinausgehen kann, bis das Skript die Sperre hält und jede ausführbare Datei, die eine Kopie davon geerbt hat seine FD-Tabelle, beendet. –

+0

@bodangly, ... kannst du mir deinen Einwand im Lichte des Klartextes von http://linux.die.net/man/2/flock erklären? –

Verwandte Themen