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 kill
und 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
kill
ist etwas falsch benannt, da es den Prozess nicht unbedingt beendet. Es sendet dem Prozess nur ein Signal. kill $PID
ist ä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, kill
der 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 0
Rückgabe bekomme , kann der Prozess mit dieser PID abgebrochen werden; und wenn die Prozess-PID (sagen wir) nicht existiert, $?
ist dies ein 1
Hinweis 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?
-p
ist zumindest in diesem Fall unnötig. ps $PID
hat 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 -n
ein gültiges Ergebnis liefert.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
ps
variieren die Optionen und Funktionen in der Regel zwischen den Plattformen, sodass sie immer noch nicht vollständig portierbar sind.
$PID
leer 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/$PID
Verzeichnis. 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/exe
ist keine reguläre Datei. Gibt also [ -f /proc/$PID/exe ]
immer ein false
Ergebnis zurück. Versuchen Sie es [ -h /proc/$PID/exe ]
.
Es scheint, als ob du willst
wait $PID
die zurückkehren wird, wenn $pid
fertig 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 $pid
weil 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, kill
was ä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.
pidof
gibt 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, pidof
legen 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 Pid
später nicht benötigen ) einfachif pidof 'process_name'; then...
pidof
Beispiel ist voller Missverständnisse darüber, wie Bash test
funktioniert. 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 $?