In einem Bash-Skript möchte ich Folgendes tun (im Pseudocode):
if [ a process exists with $PID ]; then
kill $PID
fi
Was ist der passende Ausdruck für die bedingte Anweisung?
In einem Bash-Skript möchte ich Folgendes tun (im Pseudocode):
if [ a process exists with $PID ]; then
kill $PID
fi
Was ist der passende Ausdruck für die bedingte Anweisung?
Antworten:
Verwenden Sie, um die Existenz eines Prozesses zu überprüfen
kill -0 $pid
Aber genau wie @unwind sagte, wenn du es trotzdem töten willst, einfach
kill $pid
oder Sie haben eine Rennbedingung.
Wenn Sie die Textausgabe von ignorieren killund etwas basierend auf dem Exit-Code tun möchten , können Sie dies tun
if ! kill $pid > /dev/null 2>&1; then
echo "Could not send SIGTERM to process $pid" >&2
fi
killist etwas falsch benannt, da es den Prozess nicht unbedingt beendet. Es sendet dem Prozess nur ein Signal. kill $PIDist äquivalent zu kill -15 $PID, was das Signal 15 SIGTERM an den Prozess sendet, der eine Anweisung zum Beenden ist. Es gibt kein Signal 0, das ist ein spezieller Wert, killder nur prüft, ob ein Signal an den Prozess gesendet werden kann, was für die meisten Zwecke mehr oder weniger der Überprüfung entspricht, ob es existiert. Siehe linux.die.net/man/2/kill und linux.die.net/man/7/signal
kill -0, muss ich tatsächlich Folgendes tun: kill -0 25667 ; echo $?- und wenn ich dann eine 0Rückgabe bekomme , kann der Prozess mit dieser PID abgebrochen werden; und wenn die Prozess-PID (sagen wir) nicht existiert, $?ist dies ein 1Hinweis auf einen Fehler. Ist das korrekt?
Der beste Weg ist:
if ps -p $PID > /dev/null
then
echo "$PID is running"
# Do something knowing the pid exists, i.e. the process with $PID is running
fi
Das Problem mit:
kill -0 $PID
ist, dass der Exit-Code ungleich Null ist, auch wenn die PID ausgeführt wird und Sie keine Berechtigung haben, sie zu beenden. Beispielsweise:
kill -0 1
und
kill -0 $non-running-pid
Sie haben einen nicht unterscheidbaren Exit-Code (ungleich Null) für einen normalen Benutzer, aber der Init-Prozess (PID 1) wird mit Sicherheit ausgeführt.
Die Antworten zu Kill- und Race-Bedingungen sind genau richtig, wenn der Testkörper ein "Kill" ist. Ich suchte nach dem allgemeinen " Wie testest du eine PID-Existenz in Bash?" ".
Die / proc-Methode ist interessant, bricht aber in gewissem Sinne den Geist der "ps" -Befehlsabstraktion, dh Sie müssen nicht in / proc suchen, denn was ist, wenn Linus beschließt, die "exe" -Datei etwas anderes aufzurufen?
-pist zumindest in diesem Fall unnötig. ps $PIDhat genau das gleiche Ergebnis.
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process exists"
fi
oder
if [ -n "$(ps -p $PID -o pid=)" ]
In der letzteren Form -o pid=ist ein Ausgabeformat, um nur die Prozess-ID-Spalte ohne Kopfzeile anzuzeigen. Die Anführungszeichen sind erforderlich, damit ein nicht leerer Zeichenfolgenoperator -nein gültiges Ergebnis liefert.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
psvariieren die Optionen und Funktionen in der Regel zwischen den Plattformen, sodass sie immer noch nicht vollständig portierbar sind.
$PIDleer ist, [ -e /proc/$PID ]wird immer noch true zurückgegeben, da das /proc/Verzeichnis noch vorhanden ist.
Sie haben zwei Möglichkeiten:
Beginnen wir mit der Suche nach einer bestimmten Anwendung in meinem Laptop:
[root@pinky:~]# ps fax | grep mozilla
3358 ? S 0:00 \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2 S+ 0:00 \_ grep mozilla
Alle Beispiele suchen jetzt nach PID 3358.
Erster Weg : Führen Sie "ps aux" aus und suchen Sie in der zweiten Spalte nach der PID. In diesem Beispiel suche ich nach Firefox und dann nach PID:
[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358
Ihr Code lautet also:
if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
kill $PID
fi
Zweiter Weg : Suchen Sie einfach nach etwas im /proc/$PIDVerzeichnis. Ich verwende in diesem Beispiel "exe", aber Sie können alles andere verwenden.
[root@pinky:~]# ls -l /proc/3358/exe
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash
Ihr Code lautet also:
if [ -f /proc/$PID/exe ]; then
kill $PID
fi
Übrigens: Was ist los mit kill -9 $PID || true?
BEARBEITEN:
Nachdem ich ein paar Monate darüber nachgedacht habe ... (ungefähr 24 ...), ist die ursprüngliche Idee, die ich hier gegeben habe, ein netter Hack, aber höchst unportabel. Während einige Implementierungsdetails von Linux vermittelt werden, funktioniert es unter Mac, Solaris oder * BSD nicht. Es kann sogar auf zukünftigen Linux-Kerneln fehlschlagen. Bitte - verwenden Sie "ps" wie in anderen Antworten beschrieben.
/proc/$PID/exeist keine reguläre Datei. Gibt also [ -f /proc/$PID/exe ]immer ein falseErgebnis zurück. Versuchen Sie es [ -h /proc/$PID/exe ].
Es scheint, als ob du willst
wait $PID
die zurückkehren wird, wenn $pidfertig ist.
Ansonsten können Sie verwenden
ps -p $PID
um zu überprüfen, ob der Prozess noch aktiv ist (dies ist effektiver als kill -0 $pidweil es funktioniert, auch wenn Sie die PID nicht besitzen).
pid 123 is not a child of this shell
Ich denke, das ist eine schlechte Lösung, die sich für die Rennbedingungen öffnet. Was ist, wenn der Prozess zwischen Ihrem Test und Ihrem Aufruf zum Töten abbricht? Dann wird das Töten fehlschlagen. Warum also nicht einfach den Kill in allen Fällen versuchen und seinen Rückgabewert überprüfen, um herauszufinden, wie er gelaufen ist?
kill -9. Das beendet den Prozess sofort und gibt ihm keine Chance, nach sich selbst aufzuräumen. Verwenden Sie stattdessen das, killwas äquivalent zu ist kill -15. Wenn das nicht funktioniert, sollten Sie herausfinden, warum und nur als letztes Mittel kill -9.
Hier speichere ich die PID in einer Datei namens .pid (ähnlich wie / run / ...) und führe das Skript nur aus, wenn es nicht bereits ausgeführt wird.
#!/bin/bash
if [ -f .pid ]; then
read pid < .pid
echo $pid
ps -p $pid > /dev/null
r=$?
if [ $r -eq 0 ]; then
echo "$pid is currently running, not executing $0 twice, exiting now..."
exit 1
fi
fi
echo $$ > .pid
# do things here
rm .pid
Hinweis: Es gibt eine Race-Bedingung, da nicht überprüft wird, wie diese PID aufgerufen wird. Wenn das System neu gestartet wird und .pid vorhanden ist, aber von einer anderen Anwendung verwendet wird, kann dies zu „unvorhergesehenen Konsequenzen“ führen.
In GNU / Linux können Sie beispielsweise Folgendes verwenden:
Pid=$(pidof `process_name`)
if [ $Pid > 0 ]; then
do something
else
do something
fi
Oder so ähnlich
Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN
und das zeigt dir den Namen der App, nur den Namen ohne ID.
pidofgibt keine negative Zahl zurück, da eine negative PID keinen Sinn ergibt und Sie nicht töten können init, sodass Ihre Bedingung keinen Sinn ergibt (und außerdem müssten Sie der entkommen >, um zu verhindern, dass sie eine Umleitung durchführt). Sie möchten nach einem leeren Ergebnis suchen, pidoflegen aber wie jedes anständige Tool einen Exit-Code fest, der Ihnen sagt, ob es funktioniert hat. Die richtige Lösung ist also if Pid=$(pidof 'process_name'); then ...oder (wenn Sie den Wert Pidspäter nicht benötigen ) einfachif pidof 'process_name'; then...
pidofBeispiel ist voller Missverständnisse darüber, wie Bash testfunktioniert. gnu.org/software/bash/manual/html_node/…
Der folgende Code prüft, ob mein Prozess ausgeführt wird. Wenn ja, tun Sie nichts.
Lassen Sie uns stündlich und nur dann neue Nachrichten von Amazon SQS überprüfen, wenn der Prozess nicht ausgeführt wird.
#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
/usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
echo "do nothing, just smile =)"
fi
exit $?