Ich benötige einen plattformunabhängigen (Linux/Unix | OSX) Shell/bash-Befehl, der ermittelt, ob ein bestimmter Prozess ausgeführt wird. z.B. mysqld
, httpd
... Was ist der einfachste Weg/Befehl, um dies zu tun?
Obwohl pidof
und pgrep
ein hervorragendes Werkzeug zur Ermittlung des laufenden Betriebs sind, sind beide auf einigen Betriebssystemen leider nicht verfügbar. Ein sicherer Fail-Safe wäre folgende Verwendung: ps cax | grep command
Die Ausgabe unter Gentoo Linux:
14484? S 0:00 Apache2 14667? S 0:00 Apache2 19620? Sl 0:00 Apache2 21132? Ss 0:04 Apache2
Die Ausgabe unter OS X:
42582 ?? Z 0: 00,00 (smbclient) 46529 ?? Z 0: 00,00 (smbclient) 46539 ?? Z 0: 00,00 (smbclient) 46547 ?? Z 0: 00,00 (smbclient) 46586 ?? Z 0: 00,00 (smbclient) 46594 ?? Z 0: 00,00 (smbclient)
Unter Linux und OS X gibt grep einen Exit-Code zurück, sodass Sie leicht überprüfen können, ob der Prozess gefunden wurde oder nicht.
#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
Wenn Sie außerdem die Liste der PIDs erhalten möchten, können Sie diese auch leicht eingeben:
ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
Dieser Ansatz eignet sich zum Schreiben eines einfachen leeren Zeichenfolge-Tests und zum Durchlaufen der ermittelten PIDs.
#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
echo "Process not running." 1>&2
exit 1
else
for PID in $PIDS; do
echo $PID
done
fi
Sie können es testen, indem Sie es in einer Datei (mit dem Namen "running") mit Ausführungsberechtigungen (chmod + x running) speichern und mit einem Parameter ausführen: ./running "httpd"
#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
WARNUNG!!!
Bitte beachten Sie, dass Sie lediglich die Ausgabe von ps ax
parsen, was bedeutet, dass dies, wie in der Linux-Ausgabe zu sehen ist, nicht einfach auf Prozesse abgestimmt ist, sondern auch die Argumente, die an dieses Programm übergeben werden. Ich empfehle dringend, so spezifisch wie möglich zu sein, wenn diese Methode verwendet wird (z. B. passt ./running "mysql"
auch zu 'mysqld'-Prozessen). Ich empfehle dringend, which
zu verwenden, um nach Möglichkeit einen vollständigen Pfad zu überprüfen.
Verweise:
Das Finden eines Prozesses durch den Versuch, eine Art Mustererkennung für die Prozessargumente (wie pgrep "mysqld"
) durchzuführen, ist eine Strategie, die früher oder später zum Scheitern verurteilt ist. Was ist, wenn Sie zwei mysqld laufen haben? Vergiss diesen Ansatz. Sie können es vielleicht vorübergehend richtig machen und es kann für ein oder zwei Jahre funktionieren, aber dann passiert etwas, worüber Sie nicht nachgedacht haben.
Nur die Prozess-ID (PID) ist wirklich eindeutig.
Speichern Sie die PID immer, wenn Sie etwas im Hintergrund starten. In Bash kann dies mit der $!
-Bash-Variablen erfolgen. Sie sparen sich SO damit viel Ärger.
Nun stellt sich die Frage, wie man weiß, ob eine PID läuft.
Einfach machen:
ps -o pid = -p <pid>
Dies ist POSIX und somit portabel. Die PID wird zurückgegeben, wenn der Prozess ausgeführt wird, oder nichts, wenn der Prozess nicht ausgeführt wird. Genau genommen gibt der Befehl eine einzige Spalte zurück, die pid
. Da wir jedoch einen leeren Titelheader angegeben haben (der Stoff, der unmittelbar vor dem Gleichheitszeichen steht), und dies ist die einzige angeforderte Spalte, wird der Befehl ps überhaupt keinen Header verwenden . Was wir wollen, weil es das Parsing einfacher macht.
Dies funktioniert unter Linux, BSD, Solaris usw.
Eine andere Strategie wäre, den Exit-Wert des obigen ps
-Befehls zu testen. Es sollte Null sein, wenn der Prozess läuft, und nicht Null, wenn dies nicht der Fall ist. Die POSIX-Spezifikation besagt, dass ps
> 0 beendet werden muss, wenn ein Fehler aufgetreten ist, aber mir ist unklar, was "ein Fehler" ist. Daher verwende ich diese Strategie nicht persönlich, obwohl ich mir ziemlich sicher ist, dass sie auch auf allen Unix/Linux-Plattformen funktioniert.
Bei den meisten Linux-Distributionen können Sie pidof
(8) verwenden.
Es werden die Prozess-IDs aller laufenden Instanzen angegebener Prozesse oder nichts gedruckt, wenn keine Instanzen ausgeführt werden.
Zum Beispiel auf meinem System (ich habe vier Instanzen von bash
und eine Instanz von remmina
, die ausgeführt wird):
$ pidof bash remmina
6148 6147 6144 5603 21598
Auf anderen Unices erreichen pgrep
oder eine Kombination aus ps
und grep
dasselbe, wie andere zu Recht darauf hingewiesen haben.
Der einfachste Weg ist die Verwendung von ps und grep:
command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
echo "Command is running"
else
echo "Command is not running"
fi
Wenn Ihr Befehl einige Befehlsargumente hat, können Sie nach 'grep $ command' auch mehr 'grep cmd_arg1' einfügen, um andere mögliche Prozesse herauszufiltern, die Sie nicht interessieren.
Beispiel: Zeigen Sie mir einen Java-Prozess mit angegebenem Argument:
-Djava.util.logging.config.file = logging.properties
läuft
ps ax | grep -v grep | grep Java | grep Java.util.logging.config.file=logging.properties | wc -l
Dies sollte auf den meisten Varianten von Unix, BSD und Linux funktionieren:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Getestet am:
PATH=...
]Wenn ich die verschiedenen Vorschläge zusammenfasse, ist die sauberste Version, die ich gefunden habe (ohne unzuverlässiges grep, die Teile von Wörtern auslöst):
kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
kill -0 beendet den Prozess nicht, sondern prüft, ob er existiert, und gibt dann true zurück. Wenn auf Ihrem System kein pidof vorhanden ist, speichern Sie die pid, wenn Sie den Prozess starten:
$ mysql &
$ echo $! > pid_stored
dann im Skript:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
Nur ein kleiner Zusatz: Wenn Sie das -c
-Flag zu ps hinzufügen, müssen Sie die Zeile, die den grep-Prozess enthält, nicht anschließend mit grep -v
entfernen. Das heißt.
ps acux | grep cron
sie benötigen nur ein typisches bsd-ish-System (einschließlich MacOSX). Sie können den -u
weglassen, wenn Sie weniger Informationen benötigen.
In einem System, in dem die Genetik des nativen ps
-Befehls auf SysV verweist, würden Sie dies verwenden
ps -e |grep cron
oder
ps -el |grep cron
für eine Auflistung, die mehr als nur PID und Prozessnamen enthält. Natürlich können Sie die speziellen Felder zum Ausdrucken mit der Option -o <field,field,...>
auswählen.
Ich benutze pgrep -l httpd
, bin aber nicht sicher, ob es auf einer Plattform vorhanden ist ...
Wer kann unter OSX bestätigen?
Wenn Sie es starten, wird seine PID in der Variable $!
aufgezeichnet. Speichern Sie diese PID in einer Datei.
Dann müssen Sie prüfen, ob diese PID einem laufenden Prozess entspricht. Hier ist ein komplettes Skelett-Skript:
FILE="/tmp/myapp.pid"
if [ -f $FILE ];
then
PID=$(cat $FILE)
else
PID=1
fi
ps -o pid= -p $PID
if [ $? -eq 0 ]; then
echo "Process already running."
else
echo "Starting process."
run_my_app &
echo $! > $FILE
fi
Basierend auf der Antwort von peterh
. Der Trick, um zu wissen, ob eine bestimmte PID ausgeführt wird, liegt in der ps -o pid= -p $PID
-Anweisung.
Keine der Antworten funktionierte für mich, also meine:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
Erläuterung:
|tr -d '\n'
Dadurch wird der vom Terminal erstellte Wagenrücklauf entfernt. Der Rest kann durch this post erklärt werden.
Dieser Ansatz kann verwendet werden, wenn die Befehle 'ps', 'pidof' und rest nicht zur Verfügung stehen .. Ich persönlich benutze procfs sehr häufig in meinen Tools/Skripts/Programmen.
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
Kleine Erklärung was los ist:
Dies gibt die Anzahl der Prozesse aus, deren Basisname "Chrom-Browser" ist:
ps -e -o args= | awk 'BEGIN{c=0}{
if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"
Wenn "0" ausgegeben wird, läuft der Prozess nicht. Der Befehl setzt voraus, dass der Prozesspfad kein Leerzeichen enthält. Ich habe dies nicht mit suspendierten Prozessen oder Zombie-Prozessen getestet.
Getestet mit gwak
als awk
-Alternative in Linux.
Hier ist eine vielseitigere Lösung mit einigen Anwendungsbeispielen:
#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
local quiet=1;
shift
else
local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
name=$2
if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}
process='chromium-browser'
printf "Process \"${process}\" is "
if isProcessRunning -q "$process"
then printf "running.\n"
else printf "not running.\n"; fi
printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
Hier ist meine Version. Eigenschaften:
skript:
#!/bin/bash
# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
for i in $(pidof $1); do
cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
if [ $? -eq 0 ]; then
return 0
fi
done
return 1
}
isRunning Java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
echo "not running, starting..."
fi