Ich benötige einen plattformunabhängigen Shell / Bash-Befehl (Linux / Unix | OSX), der bestimmt, ob ein bestimmter Prozess ausgeführt wird. zB mysqld
, httpd
... Was ist der einfachste Weg / Befehl , dies zu tun?
Ich benötige einen plattformunabhängigen Shell / Bash-Befehl (Linux / Unix | OSX), der bestimmt, ob ein bestimmter Prozess ausgeführt wird. zB mysqld
, httpd
... Was ist der einfachste Weg / Befehl , dies zu tun?
Antworten:
Während pidof
und pgrep
sind großartige Tools, um festzustellen, was läuft, sind beide leider auf einigen Betriebssystemen nicht verfügbar. Ein definitiver Fail-Safe wäre die Verwendung der folgenden Elemente: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 die Liste der PIDs möchten, können Sie auch leicht nach diesen suchen:
ps cax | grep httpd | grep -o '^ [] * [0-9] *'
Wessen Ausgabe ist unter Linux und OS X gleich:
3519 3521 3523 3524
Die folgende Ausgabe ist eine leere Zeichenfolge, wodurch dieser Ansatz für nicht ausgeführte Prozesse sicher ist:
Echo ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
Dieser Ansatz eignet sich zum Schreiben eines einfachen Tests auf leere Zeichenfolgen und zum anschließenden Durchlaufen der erkannten 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!!!
Beachten Sie bitte, dass Sie lediglich die Ausgabe analysieren, ps ax
was bedeutet, dass sie, wie in der Linux-Ausgabe zu sehen, nicht nur mit Prozessen übereinstimmt, sondern auch mit den an dieses Programm übergebenen Argumenten. Ich empfehle dringend, bei dieser Methode so spezifisch wie möglich zu sein (z. B. ./running "mysql"
auch für 'mysqld'-Prozesse). Ich empfehle dringend, which
wenn möglich einen vollständigen Pfad zu verwenden.
Verweise:
grep
auch finden sich (zB läuft ps cax | grep randomname
immer 0 zurück , weil grep
Funde grep randomname
(hoffe , das ist klar ...) Ein Update ist eckigen Klammern um den ersten Buchstaben des Prozessnamen hinzufügen, z. B. ps cax | grep [r]andomname
.
ps cax | rev | cut -f1 -d' ' | rev
zeigt nur die Namensspalte an, um das Parsen zu vereinfachen.
ps cax
Der Befehlsname wird möglicherweise nicht vollständig ausgegeben. ZB wird "Chrom-Browse" anstelle von "Chrom-Browser" gedruckt.
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 zwei mysqld ausgeführt werden? Vergiss diesen Ansatz. Sie können es vorübergehend richtig machen und es kann ein oder zwei Jahre lang funktionieren, aber dann passiert etwas, über das 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 viel Ärger, wenn Sie dies tun.
Nun stellt sich die Frage, ob eine PID ausgeführt wird.
Einfach machen:
ps -o pid = -p <pid>
Dies ist POSIX und daher portabel. Es wird die PID selbst zurückgeben, wenn der Prozess ausgeführt wird, oder nichts zurückgeben, wenn der Prozess nicht ausgeführt wird. Genau genommen gibt der Befehl eine einzelne Spalte zurück, die pid
, aber da wir angegeben haben, dass ein leerer Titel-Header (das Material unmittelbar vor dem Gleichheitszeichen) und dies die einzige angeforderte Spalte ist, verwendet der Befehl ps überhaupt keinen Header. Welches ist, was wir wollen, weil es das Parsen 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 ausgeführt wird, und ungleich 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 nicht klar, was "ein Fehler" ist. Daher verwende ich diese Strategie nicht persönlich, obwohl ich mir ziemlich sicher bin, dass sie auch auf allen Unix / Linux-Plattformen funktioniert.
grep <sometext>
, um einen bestimmten Prozess zu finden, etwas falsch gemacht haben, als Sie den Prozess gestartet haben, IMHO. Ich gehe von der Frage des OP aus, dass er tatsächlich die Kontrolle darüber hat, wie der Prozess gestartet wird.
Bei den meisten Linux-Distributionen können Sie pidof
(8) verwenden.
Es werden die Prozess-IDs aller ausgeführten Instanzen bestimmter Prozesse gedruckt oder nichts, wenn keine Instanzen ausgeführt werden.
Zum Beispiel auf meinem System (ich habe vier Instanzen von bash
und eine Instanz von remmina
):
$ pidof bash remmina
6148 6147 6144 5603 21598
Auf anderen Unices pgrep
oder einer Kombination von ps
und grep
wird das Gleiche erreicht, wie andere zu Recht betont haben.
pidof httpd
funktioniert gut auf Red Hat 5. Aber auf meinem Red Hat 4 pidof
ist nicht vorhanden :-(
Dies sollte auf den meisten Unix-, BSD- und Linux-Versionen funktionieren:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Getestet am:
PATH=...
]ps
. Um die zweite zu vermeiden, grep
schlage ich vor:ps aux | grep [h]ttpd
grep
.
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 enthält, können Sie nach 'grep $ command' auch mehr 'grep cmd_arg1' einfügen, um andere mögliche Prozesse herauszufiltern, an denen Sie nicht interessiert sind.
Beispiel: Zeigen Sie mir, ob ein Java-Prozess mit dem angegebenen Argument vorliegt:
-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
ps cax
entfällt die Verwendung grep -v
. So können Sie beispielsweise verwenden : ps cax | grep java > /dev/null || echo "Java not running"
.
Nur eine kleine Ergänzung: Wenn Sie das -c
Flag zu ps hinzufügen , müssen Sie die Zeile mit dem grep-Prozess grep -v
danach nicht mehr entfernen . Dh
ps acux | grep cron
ist alles, was Sie auf einem bsd-ish-System eingeben müssen (dies schließt MacOSX ein). Sie können das weglassen, -u
wenn Sie weniger Informationen benötigen.
Auf einem System, bei dem die Genetik des nativen ps
Befehls auf SysV verweist, würden Sie 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 mit dieser -o <field,field,...>
Option die spezifischen Felder auswählen, die ausgedruckt werden sollen.
Wenn ich die verschiedenen Vorschläge zusammenstelle, ist die sauberste Version, die ich finden konnte (ohne unzuverlässiges grep, das 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, prüft jedoch, ob er vorhanden ist, und gibt dann true zurück. Wenn Sie kein pidof auf Ihrem System haben, speichern Sie das 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"
Ich benutze pgrep -l httpd
, bin mir aber nicht sicher, ob es auf einer Plattform vorhanden ist ...
Wer kann es unter OSX bestätigen?
pidof
bitte auch überprüfen ? OK, hast du. Danke dir. Also sollten wir etwas anderes finden, das unter OSX funktioniert ... Ihre Basis ps|grep
könnte die Einzellösung sein ;-)
Wenn Sie es starten, wird seine PID in der $!
Variablen aufgezeichnet . Speichern Sie diese PID in einer Datei.
Dann müssen Sie überprüfen, ob diese PID einem laufenden Prozess entspricht. Hier ist ein vollständiges 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.
Dieser Ansatz kann verwendet werden, wenn die Befehle 'ps', 'pidof' und rest nicht verfügbar sind. Ich persönlich benutze procfs sehr häufig in meinen Tools / Skripten / 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 dies "0" ausgibt, wird der Prozess nicht ausgeführt. Der Befehl geht davon aus, dass der Prozesspfad kein Leerzeichen enthält. Ich habe dies nicht mit angehaltenen Prozessen oder Zombie-Prozessen getestet.
Getestet mit gwak
als awk
Alternative unter 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
Keine der Antworten hat bei mir funktioniert, also hier 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 diesen Beitrag erklärt werden .
Die folgende Shell-Funktion, die nur auf POSIX-Standardbefehlen und -optionen basiert, sollte auf den meisten (wenn nicht allen) Unix- und Linux-Systemen funktionieren. ::
isPidRunning() {
cmd=`
PATH=\`getconf PATH\` export PATH
ps -e -o pid= -o comm= |
awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
`
[ -n "$cmd" ] &&
printf "%s is running\n%s\n\n" "$1" "$cmd" ||
printf "%s is not running\n\n" $1
[ -n "$cmd" ]
}
$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd
$ isPidRunning ksh
ksh is running
5230 ksh
$ isPidRunning bash
bash is not running
Beachten Sie, dass es erstickt, wenn der zweifelhafte Befehlsname "0]" übergeben wird, und auch Prozesse nicht identifiziert, deren Namen ein eingebettetes Leerzeichen enthalten.
Beachten Sie auch, dass die am besten bewertete und akzeptierte Lösung nicht portable ps
Optionen erfordert und unentgeltlich eine Shell verwendet, die trotz ihrer Beliebtheit nicht garantiert auf jedem Unix / Linux-Computer vorhanden ist ( bash
)
$ isPidRunning 0]
druckt zB "0] läuft 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [Migration / 0] 35 [Watchdog / 0]" hier.