Linux / Unix-Befehl, um festzustellen, ob der Prozess ausgeführt wird?

97

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?

Autobahn des Lebens
quelle

Antworten:

168

Während pidofund pgrepsind 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 axwas 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, whichwenn möglich einen vollständigen Pfad zu verwenden.


Verweise:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm

Caleb Grey
quelle
Der Prozess kann ausgeführt, aber gestoppt werden. Wenn das Ziel darin besteht, zu testen, ob mysqld oder httpd "betriebsbereit" sind (antworten), sollten Sie auch prüfen, ob es gestoppt ist oder nicht.
Oluc
2
Tut mir leid, aber obwohl die Antwort aus semantischer Sicht sicherlich richtig ist, bin ich völlig dagegen, einen Prozess durch Mustervergleich auf dem Prozessarg-Vektor zu finden. Ein solcher Ansatz ist dazu verdammt, früher oder später zu scheitern (Sie geben dies tatsächlich selbst zu, indem Sie sagen, dass weitere Überprüfungen erforderlich sind). Ich habe meine eigene Empfehlung in einer separaten Antwort hinzugefügt.
Peterh
6
grepauch finden sich (zB läuft ps cax | grep randomnameimmer 0 zurück , weil grepFunde 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.
Kyle G.
ps cax | rev | cut -f1 -d' ' | revzeigt nur die Namensspalte an, um das Parsen zu vereinfachen.
Tyzoid
1
ps caxDer Befehlsname wird möglicherweise nicht vollständig ausgegeben. ZB wird "Chrom-Browse" anstelle von "Chrom-Browser" gedruckt.
Jarno
24

Sie sollten die PID kennen!

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.

So stellen Sie fest, ob der Prozess ausgeführt wird (per pid)

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 psBefehls 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.

Peterh
quelle
1
Dies beantwortet jedoch nicht die Frage, ob ein Dienst ausgeführt werden soll. Die PID wird in solchen Fällen nicht bekannt, daher diese Antwort nur dann gültig ist , wenn Sie tun die PID kennen.
Autobahn des Lebens
2
Falsch. Mein ganzer Sinn des Kommentars ist es, einen Schritt zurückzutreten und zu sagen, dass Sie, wenn Sie sich zum ersten Mal in einer Situation befinden, in der Sie irgendeine Form tun müssen 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.
Peterh
2
Der korrektere "Begriff" für die OP-Frage sollte "plattformübergreifender Befehl zum Bestimmen, ob ein Dienst ausgeführt wird" sein. Es ist nicht dasselbe System, auf dem die Prüfung ausgeführt wird, sondern ein externes System, sodass die PID einfach nicht sein wird überhaupt bekannt.
Autobahn des Lebens
2
Das ist nicht kinderleicht. Der Prozess, an dem Sie interessiert sind, ist möglicherweise abgebrochen, nachdem das System lange genug in Betrieb war, damit PIDs umlaufen können, und einem anderen Prozess wurde möglicherweise dieselbe PID zugewiesen, nach der Sie suchen. stackoverflow.com/questions/11323410/linux-pid-recycling
Claymation
1
@claymation. Gutes Argument. Die PID-Methode ist jedoch immer noch besser als der Mustervergleich bei Prozessargumenten, da ein PID-Konflikt weitaus unwahrscheinlicher ist, als beispielsweise versehentlich zwei Instanzen desselben Dienstes zu starten. Nur meine zwei Cent. :-)
Peterh
15

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 bashund eine Instanz von remmina):

$ pidof bash remmina
6148 6147 6144 5603 21598

Auf anderen Unices pgrepoder einer Kombination von psund grepwird das Gleiche erreicht, wie andere zu Recht betont haben.

Frédéric Hamidi
quelle
+1 pidof httpdfunktioniert gut auf Red Hat 5. Aber auf meinem Red Hat 4 pidofist nicht vorhanden :-(
olibre
In der Tat ist dieser Befehl weniger verbreitet als ich dachte. Ich habe meine Antwort bearbeitet, um dies klarer zu machen.
Frédéric Hamidi
Schöne, saubere Antwort. (auf unterstützten Systemen). Danke.
Mtl Dev
7

Dies sollte auf den meisten Unix-, BSD- und Linux-Versionen funktionieren:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

Getestet am:

  • SunOS 5.10 [Daher die PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Darwin 11.2.0
  • FreeBSD 9.0-STABLE
  • Red Hat Enterprise Linux ES Version 4
  • Red Hat Enterprise Linux Server Version 5
Johnsyweb
quelle
2
+1 Ja einfach ps. Um die zweite zu vermeiden, grepschlage ich vor:ps aux | grep [h]ttpd
Olibre
Ich habe den eckigen Klammertrick hier nicht verwendet, um das Einfügen einer Variablen in die Hauptvariable zu vereinfachen grep.
Johnsyweb
1
Alles klar;) Ich habe gerade auf Red Hat AS 4 und Red Hat AP 5 getestet. Natürlich arbeite ich! Sie können also Folgendes in Ihre Liste aufnehmen: Red Hat Enterprise Linux ES Version 4 und Red Hat Enterprise Linux Server Version 5 . Prost
olibre
@ Downvoter: Warum? Was habe ich verpasst? Soweit ich das beurteilen kann, führt die akzeptierte Antwort die gleiche Suche durch!
Johnsyweb
6

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
Pawel Solarski
quelle
2
Durch die Verwendung ps caxentfällt die Verwendung grep -v. So können Sie beispielsweise verwenden : ps cax | grep java > /dev/null || echo "Java not running".
Autobahn des Lebens
1
In der 3. Zeile ist ein Fehler aufgetreten. Bitte ändern Sie "running" in "$ running".
Programmierer
5

Nur eine kleine Ergänzung: Wenn Sie das -cFlag zu ps hinzufügen , müssen Sie die Zeile mit dem grep-Prozess grep -vdanach 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, -uwenn Sie weniger Informationen benötigen.

Auf einem System, bei dem die Genetik des nativen psBefehls 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.

Tatjana Heuser
quelle
Wie ist diese Antwort portabel? (Sie sagen, dass verschiedene Formen des Befehls ps auf verschiedenen Plattformen verwendet werden sollten)
Peter
ps ist leider eines dieser Tools mit unterschiedlichen Optionen für das gleiche Ergebnis, abhängig von ihrer Herkunft. Wenn Sie also nicht Ihren eigenen (wieder mit nichts anderem kompatiblen) Wrapper darum schreiben, müssen Sie die wichtigsten Linien des Erbes kennen und sich entsprechend anpassen. Beim Erstellen von Skripten ist dies anders. Dort würden Sie diese Unterschiede verwenden, um festzustellen, in welchem ​​Zweig Sie sich befinden, und um das Verhalten Ihres Skripts anzupassen. Fazit: Sie müssen beides wissen. Berühmtes Beispiel: Larry Walls "configure" -Skript. Berühmtes Zitat: Herzlichen Glückwunsch, Sie führen Eunice nicht aus.
Tatjana Heuser
5

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"
Gletscher
quelle
3

Ich benutze pgrep -l httpd, bin mir aber nicht sicher, ob es auf einer Plattform vorhanden ist ...
Wer kann es unter OSX bestätigen?

olibre
quelle
Danke @Johnsyweb. Können Sie pidofbitte auch überprüfen ? OK, hast du. Danke dir. Also sollten wir etwas anderes finden, das unter OSX funktioniert ... Ihre Basis ps|grepkönnte die Einzellösung sein ;-)
olibre
1

Sie sollten die PID Ihres Prozesses kennen.

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 $PIDAnweisung.

icarito
quelle
0

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:

  1. -m1 - Prozess beim ersten Spiel stoppen
  2. "mysqld $ | httpd $" - grep stimmt mit Zeilen überein, die auf mysqld ODER httpd endeten
  3. / proc / [0-9] * - bash stimmt mit der Zeile überein, die mit einer beliebigen Zahl begonnen hat
  4. cut - teile einfach die Ausgabe durch das Trennzeichen '/' und extrahiere Feld 3
Tom Lime
quelle
0

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 gwakals awkAlternative 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"
jarno
quelle
0

Hier ist meine Version. Eigenschaften:

  • prüft auf genauen Programmnamen (erstes Argument der Funktion). Die Suche nach "mysql" stimmt nicht mit der Ausführung von "mysqld" überein.
  • sucht Programmargumente (zweites Argument der Funktion)

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
Raigedas
quelle
0

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 .

Jeff Luyet
quelle
-1

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 psOptionen erfordert und unentgeltlich eine Shell verwendet, die trotz ihrer Beliebtheit nicht garantiert auf jedem Unix / Linux-Computer vorhanden ist ( bash)

jlliagre
quelle
$ 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.
Jarno
Wofür brauchst du das PATH-Ding?
Jarno
Die Lösung habe ich hier weiterentwickelt .
Jarno
@jarno Die PATH-Einstellung setzt voraus, dass das Skript portabel ist. Andernfalls würde es zumindest unter Solaris 10 und älter und möglicherweise unter anderen Unix-Implementierungen fehlschlagen.
Jlliagre
1
@jarno Ich könnte es tun, muss aber diese PATH-Einstellung auch für awk wiederholen. Beachten Sie, dass ich zur alten Backtick-Syntax zurückgekehrt bin, um mit Bourne-Shells vor der POSIX-Syntax portierbar zu sein.
Jlliagre