2016-07-01 11 views
4
läuft

Ich habe einen Shell-Skript mit Methoden:prüfen, ob ein Prozess läuft, und Ausgang, wenn es bereits

start(){ 
echo "Hello world" 
} 

stop(){ 
ps -ef|grep script.sh|grep -v grep|xargs kill 
} 

while [ "$1" != "" ]; do 
case "$1" in 
     start) 
      start 
      ;; 
     stop) 
      stop 
      ;; 
     *) 
      echo $"Usage: $0 {start|stop}" 
      exit 1 
     esac 
    shift 
done 

ich dieses Skript bin mit diesem Befehl: ./script.sh start den Start method.Now zu nennen, ich möchte überprüfen, ob dieser Prozess bereits ausgeführt wird und beenden, wenn er bereits ausgeführt wird. Ich habe einige Lösungen online versucht, aber nichts hat funktioniert. Jemand bitte helfen. Die Lösungen, die ich versucht haben, waren:

if [ -f /var/tmp/script.lock ]; then 
    echo "Already running. Exiting." 
    exit 1 
else 
    touch /var/tmp/script.lock 
fi 
<main script code> 
#some code 
rm /var/tmp/script.lock 

Das andere ist:

PID=$(ps -ef | grep script.sh|grep -v grep) 

    if [ -z $PID ]; then 
     echo "Process already running" 
     exit 
fi 

Diese Lösungen funktioniert nicht und beenden, auch wenn der Prozess gerade gestartet wird.

+0

Und diese Lösungen waren was? Übrigens findest du bereits alle laufenden Instanzen deines Skripts bei 'stop', kannst du nicht gleich bei' start' etwas machen? – bipll

+0

@bipll Ich habe die Lösungen hinzugefügt, die ich ausprobiert habe. Bitte überprüfen Sie und lassen Sie mich wissen, die Lösung – user6348718

+0

'-z $ ​​PID' wird wahr, wenn der Prozess * nicht * bereits läuft. – Barmar

Antwort

1

Die .lock Datei Lösung sollte funktionieren. Das einzige Problem ist, wenn das Skript aufgrund eines Fehlers beendet wird und die Sperrdatei nicht entfernt wird. Eine Verbesserung besteht darin, die PID des Prozesses in der Datei zu speichern und zu überprüfen, ob diese PID noch existiert.

if [ -f /var/tmp/script.lock ] && kill -0 $(cat /var/tmp/script.lock); then 
    echo "Already running. Exiting." 
    exit 1 
else 
    echo $$ > /var/tmp/script.lock 
fi 
<main script code> 
#some code 
rm /var/tmp/script.lock 

kill -0 nicht tatsächlich ein Signal an den Prozess senden, es prüft nur, ob es möglich ist, ein Signal zu senden: die PID vorhanden ist und Sie haben die Erlaubnis, Signale an sie zu senden (sofern Sie nicht als root laufen lassen Dies bedeutet, dass der Prozess mit derselben Benutzer-ID ausgeführt wird).

Es gibt immer noch eine entfernte Chance, dass dies eine falsche positive erhalten könnte, wenn das Skript abstürzt und dann seine PID von demselben Benutzer wiederverwendet wird. Die Wiederverwendung von PIDs sollte jedoch lange dauern, und die Wahrscheinlichkeit, dass sie von demselben Benutzer wiederverwendet werden, sollte gering sein.

Es gibt auch die Möglichkeit, dass zwei Kopien des Skripts gleichzeitig gestartet werden und beide sehen, dass es keine Sperrdatei gibt. Wenn Sie dagegen schützen müssen, sollten Sie den Befehl lockfile verwenden, um einen Mutex um den Code zu implementieren, der nach der Datei sucht.

+0

'echo $$>/var/tmp/script.lock' ist keine völlig atomare Operation - es gibt ein Fenster, wenn auch winzig, wenn die Datei existiert, aber noch keinen Inhalt hat. –

+0

@CharlesDuffy Guter Punkt, ich habe einen Vorbehalt hinzugefügt und auf den Befehl 'lockfile' verwiesen. – Barmar

+0

* nick * - sah das, und wie geändert hat das meine +1 (obwohl ich immer noch denke, dass die Frage wahrscheinlich dupe markiert werden sollte). –

1

Hier mein Skript hoffe nützlich.

#!/bin/bash 
export JAVA_HOME=/usr/java/jdk1.7.0_25 

checkpid() 
{ 
     echo $(ps -ef | grep "LiquidityWarning.jar" | grep -v grep | awk '{ print $2}') 
} 

start() 
{ 
    if [ $(checkpid) ] ; then 
     echo -e "\n$(date +%Y%m%d-%H:%M:%S) LiquidityWarning.jar is running (pid:$(checkpid))\n" 
    else 
     echo "" 
     printf "$(date +%Y%m%d-%H:%M:%S) LiquidityWarning.jar is starting..." 
     cd /app/mservice/CBTK_new 
     /usr/java/jdk1.7.0_25/bin/java -jar LiquidityWarning.jar > /dev/null 2>&1 & 

    fi 

} 

stop() 
{ 
    if [ $(checkpid) ] ; then 
     kill -9 $(checkpid) 
     echo -e "\n$(date +%Y%m%d-%H:%M:%S) LiquidityWarning.jar stop success\n" 
    fi 

} 

status() 
{ 
     if [ $(checkpid) ] ; then 
     echo -e "\n$(date +%Y%m%d-%H:%M:%S) LiquidityWarning.jar is running (pid:$(checkpid))\n" 
    else  
     echo -e "\n$(date +%Y%m%d-%H:%M:%S) LiquidityWarning.jar is not started\n" 
    fi 
} 

restart() 
{ 
     if [ $(checkpid) ] ; then 
       stop 
       sleep 2 
       start 
     else 
       echo -e "\n$(date +%Y%m%d-%H:%M:%S) LiquidityWarning.jar is not started\n" 
     fi 
} 

case "$1" in 
    start) 
     start 
     ;; 
    stop) 
     stop 
     ;; 
    restart) 
     restart 
     ;; 
    status) 
     status 
     ;; 
    *) 
    echo -e "\nUsage: $0 {start|stop|status|restart|reload}\n" 
     exit 1 
     ;; 
esac 
+0

Damit ist viel falsch. Das '-e' Argument zu' echo' sollte nur mit einer bestimmten Ursache verwendet werden (es ist eigentlich nicht konform mit der POSIX Spezifikation für 'echo' - siehe http://pubs.opengroup.org/onlinepubs/009604599/utilities/echo. html, das stattdessen 'printf% b' empfiehlt); Außerdem ist 'echo $ (foo)' im Allgemeinen eine ineffiziente und fehlerhafte Art, 'foo' auszuführen. Dazu fehlen auch Zitate an zahlreichen Stellen; Überlege, ob du es über http://shellcheck.net ausführen möchtest. –

+0

... die 'ps | Grep' Ansatz ist im Allgemeinen auch gefährlich. 'ps | grep LiquidityWarning.jar' bedeutet, dass Sie nicht nur den Dienst, sondern auch Verwaltungsbefehle wie 'scp buildserver: /path/to/new/LiquidityWarning.jar 'töten, die zufällig den Namen enthalten. Viel sicherer, ein richtiges Prozessüberwachungssystem zu verwenden, statt sich auf die Namensanpassung zu verlassen. –

+0

Danke, mein Skript läuft jetzt stabil, ich werde mein Skript verbessern. –