it-swarm.com.de

So prüfen Sie, ob eine andere Instanz meines Shell-Skripts ausgeführt wird

GNU bash, Version 1.14.7 (1)

Ich habe ein Skript mit dem Namen "abc.sh" Ich muss dies nur vom abc.sh-Skript überprüfen ... Ich habe folgende Anweisung geschrieben

status=`ps -efww | grep -w "abc.sh" | grep -v grep | grep -v $$ | awk '{ print $2 }'`
if [ ! -z "$status" ]; then
        echo "[`date`] : abc.sh : Process is already running"
        exit 1;
fi

Ich weiß, es ist falsch, weil es jedes Mal beendet wird, wenn es seinen eigenen Prozess in 'ps' gefunden hat. Wie löse ich es? Wie kann ich überprüfen, ob das Skript bereits läuft oder nicht nur from that script?

25
Jatin Bodarya

Der einfachste Weg, um zu überprüfen, ob ein Prozess bereits ausgeführt wird, ist der Befehl pidof.

if pidof -x "abc.sh" >/dev/null; then
    echo "Process already running"
fi

Oder lassen Sie Ihr Skript bei der Ausführung eine PID-Datei erstellen. Es ist dann eine einfache Übung, das Vorhandensein der PID-Datei zu überprüfen, um festzustellen, ob der Prozess bereits läuft.

#!/bin/bash
# abc.sh

mypidfile=/var/run/abc.sh.pid

# Could add check for existence of mypidfile here if interlock is
# needed in the Shell script itself.

# Ensure PID file is removed on program exit.
trap "rm -f -- '$mypidfile'" EXIT

# Create a file with current PID to indicate that process is running.
echo $$ > "$mypidfile"

...

Update: Die Frage wurde nun geändert, um das Skript selbst zu überprüfen. In diesem Fall würden wir erwarten, dass immer mindestens ein abc.sh ausgeführt wird. Wenn es mehr als einen abc.sh gibt, wissen wir, dass der Prozess noch läuft. Ich würde dennoch vorschlagen, den Befehl pidof zu verwenden, der 2 PIDs zurückgibt, wenn der Prozess bereits läuft. Sie können grep verwenden, um die aktuelle PID herauszufiltern, eine Schleife in der Shell auszuführen oder sogar nur PIDs mit wc zu zählen, um mehrere Prozesse zu erkennen. 

Hier ist ein Beispiel:

#!/bin/bash

for pid in $(pidof -x abc.sh); do
    if [ $pid != $$ ]; then
        echo "[$(date)] : abc.sh : Process is already running with PID $pid"
        exit 1
    fi
done
43
Austin Phillips

Ich will die "pidof" -Methode, hier ist der Trick:

    if pidof -o %PPID -x "abc.sh">/dev/null; then
        echo "Process already running"
    fi

Der Parameter -o %PPID gibt an, dass die PID des aufrufenden Shell- oder Shell-Skripts weggelassen werden soll. Weitere Informationen finden Sie in der Manpage pidof.

19
Aba

Hier ist ein Trick, den Sie an verschiedenen Orten sehen werden:

status=`ps -efww | grep -w "[a]bc.sh" | awk -vpid=$$ '$2 != pid { print $2 }'`
if [ ! -z "$status" ]; then
    echo "[`date`] : abc.sh : Process is already running"
    exit 1;
fi

Die Klammern um den [a] (oder einen anderen Buchstaben auswählen) verhindern, dass grep sich selbst findet. Dies macht das grep -v grep-Bit überflüssig. Ich entfernte auch den grep -v $$ und reparierte den awk-Teil, um dasselbe zu erreichen.

10
twalberg

Schießen Sie mich bitte ab, falls ich hier falsch liege

Ich verstehe, dass die mkdir-Operation atomar ist, so dass Sie ein lock directory erstellen könnten.

#!/bin/sh
lockdir=/tmp/AXgqg0lsoeykp9L9NZjIuaqvu7ANILL4foeqzpJcTs3YkwtiJ0
mkdir $lockdir  || {
    echo "lock directory exists. exiting"
    exit 1
}
# take pains to remove lock directory when script terminates
trap "rmdir $lockdir" EXIT INT KILL TERM

# rest of script here
6
glenn jackman

Verwenden Sie den Befehl PS auf eine etwas andere Art und Weise, um auch den untergeordneten Prozess zu ignorieren:

ps -eaf | grep -v grep | grep $PROCESS | grep -v $$
3
Sridhar Kumar N

pidof hat nicht für mich gearbeitet, also habe ich noch etwas gesucht und bin auf pgrep gestoßen.

for pid in $(pgrep -f my_script.sh); do
    if [ $pid != $$ ]; then
        echo "[$(date)] : my_script.sh : Process is already running with PID $pid"
        exit 1
    else
      echo "Running with PID $pid"
    fi  
done

Teilweise aus Antworten oben und https://askubuntu.com/a/803106/802276

2
Scott H

Ich erstelle während der Ausführung eine temporäre Datei.

So mache ich es:

#!/bin/sh
# check if lock file exists
if [ -e /tmp/script.lock ]; then
  echo "script is already running"
else
# create a lock file
  touch /tmp/script.lock
  echo "run script..."
#remove lock file
 rm /tmp/script.lock
fi
2
Cleber Reizen

Ich wollte abc.sh bei der Überprüfung nicht festcodieren, daher habe ich Folgendes verwendet:

MY_SCRIPT_NAME=`basename "$0"`
if pidof -o %PPID -x $MY_SCRIPT_NAME > /dev/null; then
    echo "$MY_SCRIPT_NAME already running; exiting"
    exit 1
fi
1
gorus

So mache ich es in einem Bash-Skript:

if ps ax | grep $0 | grep -v $$ | grep bash | grep -v grep
then
    echo "The script is already running."
    exit 1
fi

Dadurch kann ich dieses Snippet für ein beliebiges Bash-Skript verwenden. Ich brauchte ein Grep-Bash, weil es bei der Verwendung von cron einen anderen Prozess erstellt, der es mit/bin/sh ausführt.

1
CM Cruz

Ich habe herausgefunden, dass die Verwendung von Backticks zum Erfassen der Befehlsausgabe in einer Variablen auf abweichende Weise zu viele ps aux Ergebnisse, z. für eine einzelne ausgeführte Instanz von abc.sh :

ps aux | grep -w "abc.sh" | grep -v grep | wc -l

gibt "1" zurück. Jedoch,

count=`ps aux | grep -w "abc.sh" | grep -v grep | wc -l`
echo $count

gibt "2" zurück

Es scheint, als würde die Verwendung der Backtick-Konstruktion vorübergehend einen anderen Prozess erzeugen. Dies könnte der Grund sein, warum der Topicstarter dies nicht funktionieren konnte. Sie müssen lediglich die $ count-Var. Verringern.

1
Jimmy Falcon

Das ist kompakt und universell

# exit if another instance of this script is running
for pid in $(pidof -x `basename $0`); do
   [ $pid != $$ ] && { exit 1; }
done
0
franzisk

Ich finde die Antwort von @Austin Phillips ist genau richtig. Eine kleine Verbesserung, die ich tun würde, ist, -o hinzuzufügen (um die PID des Skripts selbst zu ignorieren) und das Skript mit dem Basisnamen abgleichen (dh derselbe Code kann in jedes Skript eingefügt werden):

if pidof -x "`basename $0`" -o $$ >/dev/null; then
    echo "Process already running"
fi
0
Andrei Neagoe