Wie kann man feststellen, ob ein Prozess ausgeführt wird oder nicht und daraus ein bedingtes Shell-Skript erstellen?

108

Wie kann ich feststellen, ob ein Prozess ausgeführt wird oder nicht, und dann ein Bash-Skript veranlassen, einige Dinge basierend auf dieser Bedingung auszuführen?

Zum Beispiel:

  • Wenn der Prozess ausgeführt abcwird, führen Sie dies aus

  • Wenn es nicht läuft, mach das.

Nirmik
quelle
1
Bitte beachten Sie, dass keine der folgenden Lösungen den Status des Prozesses berücksichtigt. Ein Kommentar zu einer meiner Fragen hat mich hierher gebracht, aber eine Antwort darauf hat mich in verschiedene Zustände eines Programms wie " zombieprocess" (nicht das, was ich als "running" -Prozess bezeichnen würde) gebracht. Eine vollständige Liste dessen, was die STATSpaltenwerte in der Ausgabe von psanzeigen, ist hier für diejenigen, die geneigt sind, eine Antwort zu schreiben, die dies berücksichtigt, oder ihre eigenen zu bearbeiten.
User66001
Zugehörige Diskussion: unix.stackexchange.com/questions/74185/…
blong
Der beste Weg, um zu überprüfen, ob ein Prozess existiert: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Antworten:

166

Ein Bash-Skript für so etwas würde ungefähr so ​​aussehen:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

Dieses Skript überprüft nur, ob das Programm "gedit" ausgeführt wird.

Oder Sie können nur überprüfen, ob das Programm nicht so läuft:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
John Vrbanac
quelle
@DreadPirateShawn Kannst du mir sagen, warum / dev / null verwendet wird und nicht einfach eine 0? Durch die Verwendung der Nummer wird der Code besser lesbar, zumindest für einen Neuling (wie mich). Keine Umleitung, kein Nichts
Silviu
2
@Silviu huh? Googeln /dev/null: „/ dev / null leitet den Befehl an die Null - Gerät Standardausgabe, die eine spezielle Vorrichtung, die die Informationen geschrieben verwirft“ ... mit 0der Befehlsausgabe in eine Datei namens würde umleiten 0. In diesem Fall würde ich empfehlen, dass Sie sich damit besser auskennen > /dev/null- Sie werden es überall sehen, da es der Standard / die richtige Art ist, Ausgaben zu verwerfen.
DreadPirateShawn
Woot danke, ich habe dies für ein nettes kleines Skript verwendet, das prüft, ob ein Programm ausgeführt wird, bevor es ausgeführt wird. (Obwohl ich es ein wenig erweitern musste, da die ausführbare Datei von Google Chrome nicht den gleichen Namen wie der Befehl run hat, lautet der Exec-Name nur
chrome
3
Fügen Sie den -xParameter hinzu, pgrepdamit er nach der genauen Anwendung sucht. Andernfalls wird er falsch korrekt, wenn er dieselbe Zeichenfolge im Namen einer anderen Anwendung findet. Ich habe nur 1 Stunde gebraucht, um das herauszufinden.
Thanos Apostolou
1
Um zu überprüfen, ob das Programm nicht ausgeführt wird, verwenden Sie! pgrep
Mohammed Noureldin
36

Jede Lösung, die so etwas verwendet ps aux | grep abcoder pgrep abcfehlerhaft ist.

Warum?

Da Sie nicht prüfen, ob ein bestimmter Prozess ausgeführt wird, prüfen Sie, ob Prozesse ausgeführt werden, die übereinstimmen abc. Jeder Benutzer kann auf einfache Weise eine ausführbare Datei mit dem Namen erstellen und ausführen abc(oder die abcirgendwo im Namen oder in den Argumenten enthalten ist), was zu einem Fehlalarm für Ihren Test führt. Es gibt verschiedene Optionen , die Sie anwenden können ps, grepund um pgrepdie Suche zu starten, aber Sie werden immer noch keinen zuverlässigen Test bekommen.

Wie teste ich zuverlässig auf einen bestimmten laufenden Prozess?

Das hängt davon ab, wofür Sie den Test benötigen.

Ich möchte sicherstellen, dass der Dienst abc ausgeführt wird, und falls nicht, starten Sie ihn

Dafür sind init und upstart da. Sie werden den Dienst starten und sicherstellen, dass seine PID in einer PID-Datei gespeichert wird. Wenn Sie versuchen, den Dienst erneut zu starten (über init oder upstart), wird die PID-Datei überprüft und entweder gestartet, wenn sie nicht vorhanden ist, oder abgebrochen, wenn sie bereits ausgeführt wird. Dies ist immer noch nicht 100% zuverlässig, aber es ist so nah wie möglich.

Weitere Lösungen finden Sie unter Wie kann ich überprüfen, ob mein Spielserver noch ausgeführt wird ?.

ABC ist mein Skript. Ich muss sicherstellen, dass nur eine Instanz meines Skripts ausgeführt wird.

Verwenden Sie in diesem Fall eine Sperrdatei oder ein Sperrverzeichnis. Z.B

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

Weitere Informationen zum Sperren finden Sie in den Bash-FAQ 45 .

geirha
quelle
3
Obwohl dies technisch gesehen stimmt, bin ich im wirklichen Leben noch nie persönlich auf ein solches Problem gestoßen. Die meisten Programme ändern ihre Namen nicht so, dass Skripte beschädigt werden. Daher ist für einfache Skripte so etwas wie pgrepoder psvöllig ausreichend und Ihr Ansatz scheint übertrieben. Wenn Sie jedoch ein Skript für die öffentliche Verbreitung schreiben, sollten Sie es so sicher wie möglich schreiben.
Scott Severance
2
Das Ändern von Namen bei @ScottSeverance-Programmen ist nicht das Problem. das würde trotzdem ein Eingreifen erfordern. Es sind andere Benutzer, die dasselbe Programm ausführen, oder andere Programme mit ähnlichen Namen, die plötzlich dazu führen, dass das Skript falsch positive Ergebnisse erzielt und somit das Falsche tut. Ich bevorzuge einfach "Werke" anstatt "meistens Werke".
Geirha
2
Ich habe falsch geschrieben. Viele von uns betreiben jedoch Einzelplatzsysteme. Und in einer Situation mit mehreren Benutzern ist es einfach, auch nach dem Benutzernamen zu suchen.
Scott Severance
1
Was passiert, wenn Ihr Skript zur Laufzeit ausfällt und abstürzt, bevor die Datei entsperrt wird?
jp093121
2
@ jp093121 Die EXIT-Trap wird ausgelöst, wenn das Skript beendet wird. Unabhängig davon, ob der Befehl beendet wird, weil er das Skriptende erreicht, einen Beendigungsbefehl enthält oder ein Signal empfängt (das verarbeitet werden kann), wird der rmBefehl ausgeführt. So lange es endet, nachdem die Falle gesetzt wurde, sollte das Schloss verschwunden sein.
Geirha
18

Das benutze ich:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

Im Klartext: Wenn 'pgrep' 0 zurückgibt, wird der Prozess ausgeführt, andernfalls nicht.


Verwandte Lesung:

Bash Scripting :: String-Vergleiche

Ubuntu Manuals pgrep

Zuul
quelle
Danke! Ich habe es auch versucht und es funktioniert auch perfekt :)
Nirmik
pgrephat die gleiche 15 Zeichen Grenze "Feature" zuvor erwähnt, so würde zum Beispiel pgrep gnome-power-managerauch fehlschlagen
Thorsen
1
Stellen Sie sicher, dass Sie die -xOption pgrep verwenden : "Nur Prozesse abgleichen, deren Name (oder Befehlszeile, wenn -f angegeben ist) genau mit dem Muster übereinstimmt."
Alastair Irvine
5

Normalerweise habe ich eine pidof -x $(basename $0)in meinen Skripten, um zu überprüfen, ob sie bereits ausgeführt werden.

Rommel Cid
quelle
2

Riffing auf @ Rommel-Cids Idee, können Sie pidofmit dem || (||), um einen Befehl auszuführen, wenn der Prozess nicht vorhanden ist, und &&, um etwas auszuführen, wenn der Prozess vorhanden ist, wodurch eine schnelle if / then / else-Bedingung erstellt wird. Hier ist zum Beispiel einer mit einem laufenden Prozess (mein Chrome-Browser, dessen Prozessname "chrome" ist) und einem Test für einen Prozess, der nicht existiert. Ich habe die Standardausgabe mit 1> / dev / null unterdrückt, damit sie nicht gedruckt wird:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$
yuvilio
quelle
1

Keine der "einfachen" Lösungen hat bei mir funktioniert, da die zu überprüfende Binärdatei nicht systemweit installiert ist. Daher muss ich den Pfad überprüfen, was wiederum die Verwendung des ps -ef | grepAnsatzes erfordert :

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi
Zeremonie
quelle
0

Das erste, was mir bei Ihrem Problem in den Sinn gekommen ist:
ps aux | grep -i abcZeigt die Details des Prozesses an, wenn er ausgeführt wird. Sie können die Anzahl der Zeilen oder die Zeit, für die sie ausgeführt werden, mit Null oder einer anderen Manipulation vergleichen. Wenn Sie den obigen Befehl ausführen, wird Ihnen mindestens eine Ausgabezeile angezeigt, dh Details über den durch diesen Befehl erstellten Prozess. Also kümmern Sie sich darum.
Das sollte ein einfacher Hack sein. Schreiben Sie es in das Bash-Skript und prüfen Sie, ob es hilfreich ist.

drake01
quelle
0

Verwenden von start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

Es funktioniert als normaler Benutzer.

Martin Monperrus
quelle
0

Ich habe festgestellt, dass die akzeptierte Antwort von @John Vrbanac bei mir nicht funktioniert und dass die Antwort von @geirha die ursprüngliche Frage nicht beantwortet.

John Vrbanacs Lösung hat nicht funktioniert, um zu überprüfen, ob ein PHP-Prozess ausgeführt wurde oder nicht. Ich verwende CentOS 7.

Die Antwort von @geirha stellt nur sicher, dass eine Instanz nicht bereits ausgeführt wird, bevor eine andere gestartet wird. Dies war nicht die ursprüngliche Frage, sondern die Frage, ob ein Prozess ausgeführt wird oder nicht.

Folgendes hat bei mir funktioniert:

Angenommen, mein Prozess hatte die Zeichenfolge "Jane" im Prozessnamen. Dies wird feststellen, ob es läuft oder nicht. Dies funktioniert für BASH- und PHP-Skripte.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
Wayne Workman
quelle
1
Ah, auch wenn dies eine Ubuntu-Q & A-Site ist, ist es nicht verwunderlich, dass einige der Antworten hier nicht auf CentOS 7 funktionieren, da Linux hier nicht zum Thema gehört. Andere Versionen von Linux werden unter unix.stackexchange.com
Elder Geek,
Obwohl der Autor der Antwort CentOS verwendet, gilt diese Antwort immer noch für Ubuntu.
Phillip-Zyan K Lee- Stockmann
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Hinweis : pgrep -x lxpaneloder pidof lxpanelmeldet weiterhin, dass lxpaneldas Programm ausgeführt wird, auch wenn es nicht mehr funktioniert (Zombie); Um den Prozess zum Leben zu erwecken, müssen wir psund verwendengrep

Bach Lien
quelle
-1

Ab dem 23. September 2016 scheint pgrep die Option "-x" zu benötigen, damit das Skript von muru funktioniert.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

Ich habe das obige Skript auf einem Ubuntu 16.04.1-Rechner ausprobiert und getestet. Genießen!

dzmanto
quelle
-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
user7449824
quelle
1
Willkommen bei Ask Ubuntu! Ich empfehle , diese Antwort zu bearbeiten , um sie mit spezifischen Details zu erweitern. (Siehe auch Wie schreibe ich eine gute Antwort ?, um allgemeine Ratschläge zu erhalten, welche Arten von Antworten auf AskUbuntu als am wertvollsten angesehen werden.)
David Foerster
-3

isProcessRunning () {if [$ (pidof $ 1)> / dev / null]; dann retval = 'true'; sonst retval = 'false'; fi; echo $ retval; }

isProcessRunning geany

wahr

Dominic
quelle