Richtiges Sperren in Shell-Skripten?

66

Manchmal müssen Sie sicherstellen, dass nur eine Instanz eines Shell-Skripts gleichzeitig ausgeführt wird.

Zum Beispiel ein Cron-Job, der über Crond ausgeführt wird und keine eigene Sperre bietet (z. B. der Standard-Solaris-Crond).

Ein gängiges Muster zum Implementieren von Sperren ist folgender Code:

#!/bin/sh
LOCK=/var/tmp/mylock
if [ -f $LOCK ]; then            # 'test' -> race begin
  echo Job is already running\!
  exit 6
fi
touch $LOCK                      # 'set'  -> race end
# do some work
rm $LOCK

Natürlich hat ein solcher Code eine Racebedingung. Es gibt ein Zeitfenster, in dem die Ausführung von zwei Instanzen nach Zeile 3 fortgesetzt werden kann, bevor eine die $LOCKDatei berühren kann.

Für einen Cron-Job ist dies normalerweise kein Problem, da zwischen zwei Aufrufen ein Intervall von Minuten liegt.

Aber Dinge können schief gehen - zum Beispiel, wenn sich die Sperrdatei auf einem NFS-Server befindet - das hängt. In diesem Fall können mehrere Cron-Jobs in Zeile 3 blockiert und in die Warteschlange gestellt werden. Wenn der NFS-Server wieder aktiv ist, haben Sie eine donnernde Herde parallel laufender Jobs.

Beim Durchsuchen des Webs habe ich das Tool Lockrun gefunden, das eine gute Lösung für dieses Problem zu sein scheint. Damit führen Sie ein Skript aus, das wie folgt gesperrt werden muss:

$ lockrun --lockfile=/var/tmp/mylock myscript.sh

Sie können dies in eine Hülle packen oder von Ihrer Crontab verwenden.

Es verwendet lockf()(POSIX), falls verfügbar, und greift auf flock()(BSD) zurück. Und lockf()Unterstützung über NFS sollte relativ weit verbreitet sein.

Gibt es Alternativen zu lockrun?

Was ist mit anderen Cron-Daemons? Gibt es gewöhnliche Kronen, die eine sichere Verriegelung unterstützen? Ein kurzer Blick in die Manpage von Vixie Crond (Standard auf Debian / Ubuntu-Systemen) zeigt nichts über das Sperren.

Wäre es eine gute Idee, ein Tool wie lockrunin coreutils aufzunehmen ?

Meiner Meinung nach implementiert es ein Thema sehr ähnlich timeout, niceund Freunde.

maxschlepzig
quelle
4
Tangential und zum Wohle anderer, die Ihr anfängliches Muster für gut genug halten, sollte dieser Shell-Code möglicherweise TERM abfangen, um seine Sperrdatei zu entfernen, wenn er bearbeitet wird kill. und es scheint eine gute Praxis zu sein, die eigene PID in der Schlossdatei zu speichern, anstatt sie nur zu berühren.
Ulrich Schwarz
@Shawn erwähnt crond und NFS nicht wirklich.
Maxschlepzig
verwandte Frage zu SO: stackoverflow.com/questions/185451/…
maxschlepzig
1
@Ulrich sehr spät, Speichern einer PID in einer NFS-Sperrdatei fügt sehr wenig Wert. Selbst das Hinzufügen des Hostnamens hilft nicht wirklich bei der
Suche

Antworten:

45

Hier ist eine andere Möglichkeit, das Sperren in einem Shell-Skript durchzuführen, um die oben beschriebene Race-Bedingung zu verhindern, bei der zwei Jobs möglicherweise Zeile 3 passieren. Die noclobberOption funktioniert in ksh und bash. Nicht verwenden, set noclobberda Sie kein Scripting in csh / tcsh ausführen sollten. ;)

lockfile=/var/tmp/mylock

if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then

        trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT

        # do stuff here

        # clean up after yourself, and release your trap
        rm -f "$lockfile"
        trap - INT TERM EXIT
else
        echo "Lock Exists: $lockfile owned by $(cat $lockfile)"
fi

YMMV mit Sperrung für NFS (Sie wissen, wenn NFS-Server nicht erreichbar sind), aber im Allgemeinen ist es viel robuster als früher. (vor 10 Jahren)

Wenn Sie Cron-Jobs haben, die zur gleichen Zeit auf mehreren Servern dasselbe tun, aber nur eine Instanz zur Ausführung benötigen, funktioniert dies möglicherweise für Sie.

Ich habe keine Erfahrung mit Lockrun, aber es könnte hilfreich sein, eine voreingestellte Sperrumgebung zu haben, bevor das Skript tatsächlich ausgeführt wird. Oder vielleicht auch nicht. Sie setzen lediglich den Test für die Sperrdatei außerhalb Ihres Skripts in einem Wrapper und könnten theoretisch nicht dieselbe Race-Bedingung erfüllen, wenn zwei Jobs genau zur gleichen Zeit von lockrun aufgerufen würden, genau wie bei 'inside- the-script 'lösung?

Das Sperren von Dateien ist sowieso ein ehrenwertes Verhalten des Systems, und alle Skripte, die vor der Ausführung nicht auf das Vorhandensein der Sperrdatei prüfen, tun das, was sie tun werden. Indem Sie den Lockfile-Test und das richtige Verhalten durchführen, lösen Sie 99% der potenziellen Probleme, wenn nicht sogar 100%.

Wenn Sie häufig mit Lockfile-Rennen konfrontiert sind, kann dies ein Hinweis auf ein größeres Problem sein, z. B. dass Ihre Jobs nicht richtig terminiert sind, oder wenn das Intervall nicht so wichtig ist wie die Beendigung des Jobs, ist Ihr Job möglicherweise besser für die Dämonisierung geeignet .


BEARBEITEN UNTEN - 2016-05-06 (wenn Sie KSH88 verwenden)


Basieren Sie auf @Clint Pachls Kommentar unten, wenn Sie ksh88 verwenden, verwenden Sie mkdiranstelle von noclobber. Dies mindert meistens eine potenzielle Rennbedingung, schränkt sie jedoch nicht vollständig ein (obwohl das Risiko winzig ist). Für weitere Informationen lesen Sie den Link, den Clint unten gepostet hat .

lockdir=/var/tmp/mylock
pidfile=/var/tmp/mylock/pid

if ( mkdir ${lockdir} ) 2> /dev/null; then
        echo $$ > $pidfile
        trap 'rm -rf "$lockdir"; exit $?' INT TERM EXIT
        # do stuff here

        # clean up after yourself, and release your trap
        rm -rf "$lockdir"
        trap - INT TERM EXIT
else
        echo "Lock Exists: $lockdir owned by $(cat $pidfile)"
fi

Ein zusätzlicher Vorteil ist, dass Sie, wenn Sie in Ihrem Skript tmpfiles erstellen müssen, das lockdirVerzeichnis für diese Dateien verwenden können, da Sie wissen, dass diese beim Beenden des Skripts bereinigt werden.

Für modernere Bash sollte die Noclobber-Methode oben geeignet sein.

Tim Kennedy
quelle
1
Nein, mit Lockrun haben Sie kein Problem - wenn ein NFS-Server hängt, hängen alle Lockrun-Aufrufe (zumindest) im lockf()Systemaufruf - wenn es gesichert ist, werden alle Prozesse fortgesetzt, aber nur ein Prozess gewinnt die Sperre. Keine Racebedingung. Ich stoße bei Cronjobs nicht oft auf solche Probleme - das Gegenteil ist der Fall - aber dies ist ein Problem, wenn es Sie trifft, kann es sehr schmerzhaft sein.
maxschlepzig
1
Ich habe diese Antwort akzeptiert, weil die Methode sicher und bisher die eleganteste ist. Ich schlage eine kleine Variante vor: set -o noclobber && echo "$$" > "$lockfile"um einen sicheren Fallback zu erhalten, wenn die Shell die Option noclobber nicht unterstützt.
maxschlepzig
3
Gute Antwort, aber Sie sollten auch den Wert in lockfile "kill -0", um sicherzustellen, dass der Prozess, der die Sperre erstellt hat, noch vorhanden ist.
Nigel Horne
1
Die noclobberOption ist möglicherweise anfällig für Rennbedingungen. Unter mywiki.wooledge.org/BashFAQ/045 finden Sie einige Denkanstöße.
Clint Pachl
2
Hinweis: Die Verwendung von noclobber(oder -C) in ksh88 funktioniert nicht, da ksh88 nicht O_EXCLfür verwendet wird noclobber. Wenn Sie mit einer neueren Shell arbeiten, sind Sie möglicherweise in Ordnung ...
jrw32982
14

Ich bevorzuge harte Links.

lockfile=/var/lock/mylock
tmpfile=${lockfile}.$$
echo $$ > $tmpfile
if ln $tmpfile $lockfile 2>&-; then
    echo locked
else
    echo locked by $(<$lockfile)
    rm $tmpfile
    exit
fi
trap "rm ${tmpfile} ${lockfile}" 0 1 2 3 15
# do what you need to

Harte Links sind atomar über NFS und zum größten Teil auch über mkdir . Verwenden mkdir(2)oder link(2)sind auf praktischer Ebene ungefähr gleich; Ich bevorzuge nur die Verwendung von Hardlinks, da mehr Implementierungen von NFS atomare Hardlinks als atomare zuließen mkdir. Mit modernen Versionen von NFS sollten Sie sich auch keine Sorgen mehr machen müssen.

Arcege
quelle
12

Ich verstehe, dass mkdirdas atomar ist, also vielleicht:

lockdir=/var/tmp/myapp
if mkdir $lockdir; then
  # this is a new instance, store the pid
  echo $$ > $lockdir/PID
else
  echo Job is already running, pid $(<$lockdir/PID) >&2
  exit 6
fi

# then set traps to cleanup upon script termination 
# ref http://www.shelldorado.com/goodcoding/tempfiles.html
trap 'rm -r "$lockdir" >/dev/null 2>&1' 0
trap "exit 2" 1 2 3 13 15
Glenn Jackman
quelle
Ok, aber ich konnte keine Informationen finden, ob mkdir()über NFS (> = 3) standardisiert ist, atomar zu sein.
maxschlepzig
2
@maxschlepzig RFC 1813 ruft nicht explizit dazu mkdirauf, atomar zu sein (es tut es für rename). In der Praxis ist bekannt, dass einige Implementierungen dies nicht sind. Verwandte: ein interessanter Thread, einschließlich eines Beitrags des Autors von GNU Arch .
Gilles
8

Eine einfache Möglichkeit ist die Verwendung, lockfiledie normalerweise mit dem procmailPaket geliefert wird.

LOCKFILE="/tmp/mylockfile.lock"
# try once to get the lock else exit
lockfile -r 0 "$LOCKFILE" || exit 0

# here the actual job

rm -f "$LOCKFILE"
Jofel
quelle
5

semDas, was als Teil der GNU- parallelTools kommt, könnte das sein, wonach Sie suchen:

sem [--fg] [--id <id>] [--semaphoretimeout <secs>] [-j <num>] [--wait] command

Wie in:

sem --id my_semaphore --fg "echo 1 ; date ; sleep 3" &
sem --id my_semaphore --fg "echo 2 ; date ; sleep 3" &
sem --id my_semaphore --fg "echo 3 ; date ; sleep 3" &

Ausgabe:

1
Thu 10 Nov 00:26:21 UTC 2016
2
Thu 10 Nov 00:26:24 UTC 2016
3
Thu 10 Nov 00:26:28 UTC 2016

Bitte beachten Sie, dass die Bestellung nicht garantiert wird. Auch die Ausgabe wird erst am Ende angezeigt (irritierend!). Trotzdem ist es die präziseste Methode, die ich kenne, um sich vor gleichzeitiger Ausführung zu schützen, ohne sich um Sperrdateien, Wiederholungsversuche und Bereinigung zu sorgen.

Teilweise bewölkt
quelle
Wird die durch den semGriff gebotene Verriegelung während der Ausführung abgeschossen?
Roaima
2

Ich benutze dtach.

$ dtach -n /tmp/socket long_running_task ; echo $?
0
$ dtach -n /tmp/socket long_running_task ; echo $?
dtach: /tmp/socket: Address already in use
1
AndresVia
quelle
1

Ich verwende das Befehlszeilentool "flock", um Sperren in meinen Bash-Skripten zu verwalten, wie hier und hier beschrieben . Ich habe diese einfache Methode aus der Flock-Manpage verwendet, um einige Befehle in einer Subshell auszuführen ...

   (
     flock -n 9
     # ... commands executed under lock ...
   ) 9>/var/lock/mylockfile

In diesem Beispiel schlägt der Exit-Code 1 fehl, wenn die Sperrdatei nicht abgerufen werden kann. Flock kann aber auch so verwendet werden, dass keine Befehle in einer Sub-Shell ausgeführt werden müssen :-)

dru8274
quelle
3
Der flock()Systemaufruf funktioniert nicht über NFS .
maxschlepzig
1
BSD hat ein ähnliches Tool, "lockf".
dubiousjim
2
@dubiousjim, BSD lockf ruft auch auf flock()und ist damit problematisch über NFS. Übrigens greift flock () unter Linux inzwischen auf fcntl()Dateien zurück, die sich auf einem NFS-Mount befinden. In einer reinen Linux-NFS-Umgebung flock()funktioniert dies nun über NFS.
Maxschlepzig
1

Benutze keine Datei.

Wenn Ihr Skript so ausgeführt wird, zB:

bash my_script

Sie können erkennen, ob es ausgeführt wird, indem Sie Folgendes verwenden:

running_proc=$(ps -C bash -o pid=,cmd= | grep my_script);
if [[ "$running_proc" != "$$ bash my_script" ]]; do 
  echo Already locked
  exit 6
fi
frogstarr78
quelle
Hm, läuft der ps-Prüfcode von innen my_script? Falls eine andere Instanz ausgeführt wird - enthält sie nicht running_proczwei übereinstimmende Zeilen? Ich mag die Idee, aber natürlich - Sie werden falsche Ergebnisse erhalten, wenn ein anderer Benutzer ein Skript mit dem gleichen Namen
ausführt
3
Es enthält auch eine Race-Bedingung: Wenn 2 Instanzen die erste Zeile parallel ausführen, erhält keine die 'Sperre' und beide beenden mit dem Status 6. Dies wäre eine Art von einer Runde gegenseitigem Verhungern . Übrigens bin ich mir nicht sicher, warum Sie $!statt $$in Ihrem Beispiel verwenden.
maxschlepzig
@maxschlepzig ja sorry wegen dem falschen $! $$
frogstarr78 05.10.11
@maxschlepzig Um mehrere Benutzer zu behandeln, die das Skript ausführen, fügen Sie euser = zum Argument -o hinzu.
Frogstarr78
@maxschlepzig Um Mehrfachzeilen zu vermeiden, können Sie auch die Argumente in grep oder zusätzliche "Filter" (zB grep -v $$) ändern . Grundsätzlich habe ich versucht, eine andere Herangehensweise an das Problem zu finden.
Frogstarr78
1

Für die tatsächliche Verwendung sollten Sie die am besten bewertete Antwort verwenden .

Ich möchte jedoch einige verschiedene kaputte und teilweise umsetzbare Ansätze psund die vielen Vorbehalte, die sie haben, diskutieren , da ich immer wieder sehe, wie Leute sie verwenden.

Diese Antwort ist wirklich die Antwort auf "Warum nicht das Sperren in der Shell verwenden psund grepdamit umgehen?"

Unterbrochener Ansatz # 1

Zunächst ein Ansatz in einer anderen Antwort , der ein paar positive Stimmen hat, obwohl er nicht funktioniert (und niemals funktionieren könnte) und eindeutig niemals getestet wurde:

running_proc=$(ps -C bash -o pid=,cmd= | grep my_script);
if [[ "$running_proc" != "$$ bash my_script" ]]; do 
  echo Already locked
  exit 6
fi

Korrigieren wir die Syntaxfehler und die fehlerhaften psArgumente und erhalten:

running_proc=$(ps -C bash -o pid,cmd | grep "$0");
echo "$running_proc"
if [[ "$running_proc" != "$$ bash $0" ]]; then
  echo Already locked
  exit 6
fi

Dieses Skript wird immer beendet , unabhängig davon, wie Sie es ausführen.

Wenn Sie es mit ausführen ./myscript, pswird nur die Ausgabe angezeigt 12345 -bash, die nicht mit der erforderlichen Zeichenfolge übereinstimmt 12345 bash ./myscript, sodass dies fehlschlägt.

Wenn Sie es mit ausführen bash myscript, werden die Dinge interessanter. Der Bash-Prozess fordert zum Ausführen der Pipeline auf, und die untergeordnete Shell führt das psund aus grep. Sowohl die ursprüngliche Shell als auch die untergeordnete Shell werden in der psAusgabe wie folgt angezeigt :

25793 bash myscript
25795 bash myscript

Das ist nicht die erwartete Ausgabe $$ bash $0, daher wird Ihr Skript beendet.

Unterbrochene Annäherung # 2

Nun habe ich dem Benutzer, der den fehlerhaften Ansatz # 1 geschrieben hat, etwas Ähnliches angetan, als ich das erste Mal versuchte:

if otherpids="$(pgrep -f "$0" | grep -vFx "$$")" ; then
  echo >&2 "There are other copies of the script running; exiting."
  ps >&2 -fq "${otherpids//$'\n'/ }" # -q takes about a tenth the time as -p
  exit 1
fi

Das funktioniert fast . Aber die Tatsache, dass man sich gabelt, um die Pfeife laufen zu lassen, wirft dies weg. Also wird dieser auch immer aussteigen.

Unzuverlässiger Ansatz # 3

pids_this_script="$(pgrep -f "$0")"
if not_this_process="$(echo "$pids_this_script" | grep -vFx "$$")"; then
  echo >&2 "There are other copies of this script running; exiting."
  ps -fq "${not_this_process//$'\n'/ }"
  exit 1
fi

Diese Version vermeidet das Pipeline-Forking-Problem in Ansatz 2, indem zuerst alle PIDs mit dem aktuellen Skript in den Befehlszeilenargumenten abgerufen und dann diese PID-Liste separat gefiltert werden, um die PID des aktuellen Skripts wegzulassen.

Dies könnte funktionieren ... vorausgesetzt, kein anderer Prozess verfügt über eine entsprechende Befehlszeile $0und das Skript wird immer auf die gleiche Weise aufgerufen (z. B. wenn es mit einem relativen Pfad und dann einem absoluten Pfad aufgerufen wird, bemerkt die letztere Instanz den ersteren nicht ).

Unzuverlässiger Ansatz # 4

Was ist, wenn wir die Überprüfung der vollständigen Befehlszeile überspringen, da dies möglicherweise nicht auf ein aktuell ausgeführtes Skript hinweist, und lsofstattdessen überprüfen, ob alle Prozesse mit diesem Skript geöffnet sind?

Na ja, dieser Ansatz ist eigentlich gar nicht so schlecht:

if otherpids="$(lsof -t "$0" | grep -vFx "$$")"; then
  echo >&2 "Error: There are other processes that have this script open - most likely other copies of the script running.  Exiting to avoid conflicts."
  ps >&2 -fq "${otherpids//$'\n'/ }"
  exit 1
fi

Wenn eine Kopie des Skripts ausgeführt wird, wird die neue Instanz natürlich einwandfrei gestartet, und es werden zwei Kopien ausgeführt.

Oder wenn das ausgeführte Skript geändert wird (z. B. mit Vim oder mit a git checkout), startet die "neue" Version des Skripts problemlos, da sowohl Vim als auch git checkouteine neue Datei (ein neuer Inode) anstelle des altes.

Allerdings , wenn das Skript nie geändert wird und nie kopiert, dann ist diese Version ziemlich gut. Es gibt keine Racebedingung, da die Skriptdatei bereits geöffnet sein muss, bevor die Prüfung erreicht werden kann.

Es kann immer noch Fehlalarme geben, wenn die Skriptdatei in einem anderen Prozess geöffnet ist. Beachten Sie jedoch, dass vim die Skriptdatei auch dann nicht geöffnet hält, wenn sie in Vim bearbeitet werden kann, sodass keine Fehlalarme auftreten.

Denken Sie jedoch daran, dass Sie diesen Ansatz nicht verwenden sollten, wenn das Skript bearbeitet oder kopiert werden könnte, da Sie falsche Negative erhalten, dh mehrere Instanzen gleichzeitig ausgeführt werden für dich. Ich erwähne es jedoch, weil Ansatz Nr. 3 falsch positive Ergebnisse liefert (dh den Start verweigert), wenn Sie das Skript mit Vim geöffnet haben.

Also, was ist dann zu tun?

Die am häufigsten gewählte Antwort auf diese Frage liefert einen soliden Ansatz.

Vielleicht können Sie eine bessere schreiben ... aber wenn Sie nicht alle Probleme und Vorbehalte bei den oben genannten Ansätzen verstehen, ist es unwahrscheinlich, dass Sie eine Sperrmethode schreiben, die sie alle vermeidet.

Platzhalter
quelle
0

Hier ist etwas, das ich manchmal auf einem Server hinzufüge, um die Rennbedingungen für jeden Job auf der Maschine einfach zu handhaben. Es ähnelt dem Beitrag von Tim Kennedy, aber auf diese Weise erhalten Sie die Rennhandhabung, indem Sie jedem Bash-Skript, das es benötigt, nur eine Zeile hinzufügen.

Fügen Sie den folgenden Inhalt in zB / opt / racechecker / racechecker ein:

ZPROGRAMNAME=$(readlink -f $0)
EZPROGRAMNAME=`echo $ZPROGRAMNAME | sed 's/\//_/g'`
EZMAIL="/usr/bin/mail"
EZCAT="/bin/cat"

if  [ -n "$EZPROGRAMNAME" ] ;then
        EZPIDFILE=/tmp/$EZPROGRAMNAME.pid
        if [ -e "$EZPIDFILE" ] ;then
                EZPID=$($EZCAT $EZPIDFILE)
                echo "" | $EZMAIL -s "$ZPROGRAMNAME already running with pid $EZPID"  alarms@someemail.com >>/dev/null
                exit -1
        fi
        echo $$ >> $EZPIDFILE
        function finish {
          rm  $EZPIDFILE
        }
        trap finish EXIT
fi

Hier ist, wie man es benutzt. Beachten Sie die Zeile nach dem Schebang:

     #/bin/bash
     . /opt/racechecker/racechecker
     echo "script are running"
     sleep 120

Die Art und Weise, wie es funktioniert, ist, dass es den Namen der Haupt-BashScript-Datei herausfindet und eine PID-Datei unter "/ tmp" erstellt. Außerdem wird dem Endsignal ein Listener hinzugefügt. Der Listener entfernt die PID-Datei, wenn das Hauptskript ordnungsgemäß abgeschlossen ist.

Wenn beim Starten einer Instanz eine PID-Datei vorhanden ist, wird stattdessen die if-Anweisung ausgeführt, die den Code in der zweiten if-Anweisung enthält. In diesem Fall habe ich beschlossen, in diesem Fall eine Alarmmail zu starten.

Was ist, wenn das Skript abstürzt?

Eine weitere Übung wäre, mit Abstürzen umzugehen. Idealerweise sollte die PID-Datei entfernt werden, auch wenn das Hauptskript aus irgendeinem Grund abstürzt. Dies ist in meiner obigen Version nicht der Fall. Das heißt, wenn das Skript abstürzt, muss die PID-Datei manuell entfernt werden, um die Funktionalität wiederherzustellen.

Im Falle eines Systemabsturzes

Es ist eine gute Idee, die PID-Datei / Sperrdatei unter zum Beispiel / tmp zu speichern. Auf diese Weise werden Ihre Skripte nach einem Systemabsturz definitiv weiter ausgeführt, da die PID-Dateien beim Booten immer gelöscht werden.

Zick-Zack-Staub
quelle
Im Gegensatz zu Tim Kennedys Ansatz enthält Ihr Skript eine Race-Bedingung. Dies liegt daran, dass Sie das Vorhandensein der PIDFILE und ihre bedingte Erstellung nicht in einer atomaren Operation überprüfen.
Maxschlepzig
+1 dazu! Ich werde dies berücksichtigen und mein Skript modifizieren.
Ziggestardust
-2

Überprüfen Sie mein Skript ...

Du darfst es LIEBEN ...

[rambabu@Server01 ~]$ sh Prevent_cron-OR-Script_against_parallel_run.sh
Parallel RUN Enabled
Now running
Task completed in Parallel RUN...
[rambabu@Server01 ~]$ cat Prevent_cron-OR-Script_against_parallel_run.sh
#!/bin/bash
#Created by RambabuKella
#Date : 12-12-2013

#LOCK file name
Parallel_RUN="yes"
#Parallel_RUN="no"
PS_GREP=0
LOCK=/var/tmp/mylock_`whoami`_"$0"
#Checking for the process
PS_GREP=`ps -ef |grep "sh $0" |grep -v grep|wc -l`
if [ "$Parallel_RUN" == "no" ] ;then
echo "Parallel RUN Disabled"

 if [ -f $LOCK ] || [ $PS_GREP -gt 2   ] ;then
        echo -e "\nJob is already running OR LOCK file exists. "
        echo -e "\nDetail are : "
        ps -ef |grep  "$0" |grep -v grep
        cat "$LOCK"
  exit 6
 fi
echo -e "LOCK file \" $LOCK \" created on : `date +%F-%H-%M` ." &> $LOCK
# do some work
echo "Now running"
echo "Task completed on with single RUN ..."
#done

rm -v $LOCK 2>/dev/null
exit 0
else

echo "Parallel RUN Enabled"

# do some work
echo "Now running"
echo "Task completed in Parallel RUN..."
#done

exit 0
fi
echo "some thing wrong"
exit 2
[rambabu@Server01 ~]$
user54178
quelle
-3

Ich biete die folgende Lösung in einem Skript mit dem Namen "flocktest" an

#!/bin/bash
export LOGFILE=`basename $0`.logfile
logit () {
echo "$1" >>$LOGFILE
}
PROGPATH=$0
(
flock -x -n 257
(($?)) && logit "'$PROGPATH' is already running!" && exit 0
logit "'$PROGPATH', proc($$): sleeping 30 seconds"
sleep 30
)257<$PROGPATH
Newton T Hammet Jr
quelle