Die "richtige" Methode, um zu testen, ob ein Dienst in einem Skript ausgeführt wird

96

Mein Problem:

Ich schreibe ein Bash-Skript und möchte darin überprüfen, ob ein bestimmter Dienst ausgeführt wird.

Ich weiß, wie man das manuell macht, mit $ service [service_name] status.

Aber (vor allem seit dem Umstieg auf systemd) wird eine ganze Reihe von Text gedruckt, deren Analyse etwas unübersichtlich ist. Ich nahm an, es gibt einen Befehl für Skripte mit einfacher Ausgabe oder einen Rückgabewert, den ich überprüfen kann.

Aber googeln um ergibt nur eine Tonne „Oh, nur ps aux | grep -v grep | grep [service_name]“ Ergebnisse. Das kann doch nicht die beste Übung sein, oder? Was ist, wenn eine andere Instanz dieses Befehls ausgeführt wird, aber keine, die vom SysV-Init-Skript gestartet wurde?

Oder sollte ich einfach die Klappe halten und mir die Hände mit einem kleinen Pgrep schmutzig machen?

Nick S
quelle

Antworten:

139

systemctlhat einen is-activeUnterbefehl dafür:

systemctl is-active --quiet service

wird mit dem Status Null beendet, wenn serviceaktiv, andernfalls mit einem Wert ungleich Null, was es ideal für Skripte macht:

systemctl is-active --quiet service && echo Service is running

Wenn Sie dies weglassen --quiet, wird auch der aktuelle Status auf die Standardausgabe ausgegeben.

Wie von don_crissti hervorgehoben , können einige Einheiten aktiv sein, obwohl nichts läuft, um den Dienst bereitzustellen: Einheiten, die als "RemainAfterExit" markiert sind, werden als aktiv betrachtet, wenn sie erfolgreich beendet werden ( zB konfigurieren sie einen Aspekt des Systems). Einheiten, an denen Dämonen beteiligt sind, sind jedoch nur aktiv, wenn der Dämon noch ausgeführt wird.

Stephen Kitt
quelle
Vorsicht bei OneShot-Diensten. Sie sind nur inactiveoder activatingund beide systemctl statusund beenden systemctl is-activemit 3. (ab systemd-241 ) Workaround:systemctl show service | grep -qx ActiveStatus=activating
Alois Mahdal
@Alois Ich frage mich, auf welche Szenarien Sie gestoßen sind, wenn Sie einen Oneshot-Dienst als aktiv betrachten möchten. hast du ein beispiel
Stephen Kitt
Sicher, @StephenKitt. Das Tool foonimmt Systemänderungen vor, bei denen ein Neustart erforderlich ist, und verwendet einen einmaligen Dienst, beispielsweise foo_cleanupbeim nächsten Start , um die Daten zu bereinigen. Ich teste dies (mein Skript ist auch als Dienst geplant) und möchte später Fehler sammeln, aber wann ist es danach (vsauce music)? Nun, eines der Kriterien ist, dass foo_cleanupes zu Ende ist ("aufgehört, aktiv zu sein").
Alois Mahdal
Es ist möglicherweise erwähnenswert, darauf hinzuweisen, dass "ist fehlgeschlagen" ebenfalls eine Option ist. Dies ist hilfreich, wenn Sie eine Aktion ausführen müssen, die auf einem nicht gestarteten Dienst basiert.
Phill Healey
33

systemctlhat einen Modus, der für Scripting geeignet ist; Verwenden Sie showstattdessen statusund fügen Sie die Optionen -p/ --propertiesund hinzu --value, um nur die gewünschte Ausgabe zu erhalten.

Hier ist ein Beispiel (von einem Ubuntu 17.04-System):

$ systemctl show -p SubState --value NetworkManager
running

Laufen (oder anders) ist a SubState. Wenn Sie wissen möchten, ob ein Dienst aktiv ist, verwenden Sie die EigenschaftActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

Notizen von der man:

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".
Zanna
quelle
2
+1 für anspruchsvolle Antwort. Bitte geben Sie die Distributionen an, die die --versionOption mit systemctl akzeptieren .
SK Venkat
11

Als Ergänzung zu Zannas Antwort wurde die --valueOption für systemctl showmit Version 230 von systemd eingeführt . Daher ist es in bestimmten Distributionen wie Debian Jessie möglicherweise nicht verfügbar.

In diesem Fall kann die Option mit sed emuliert werden:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running
Oxmel
quelle
1
+1 für darauf hingewiesen, die --value Intro-Version & Distribution, die nicht funktionieren wird.
SK Venkat
3

Ich finde dies nützlich für die Befehlszeilenausführung oder wenn Sie Skripte erstellen.

Kopiert von @StephenKitt

Dadurch wird überprüft, ob der Dienst inaktiv ist, und ein Neustart des Dienstes durchgeführt

systemctl is-active --quiet <service name> || <service name> restart

die ||es überprüft , ob der Rückgabewert von systemctl Nicht-Null Bedeutung ist , wenn es nicht aktiv ist , wie vom Autor erklärt.

Sternchen
quelle
Sie können auch `is-failed´ verwenden, um zu testen, ob ein Neustart erforderlich ist. Es scheint etwas intuitiver zu sein, um einen fehlgeschlagenen Dienst neu zu starten.
Phill Healey
ja, aber für mich wollte ich mich üben und davon ausgehen, dass alles läuft, wenn es nicht läuft. damit kann ich andere Sachen überprüfen. Wenn Sie nur überprüfen möchten, ob das Programm nicht ausgeführt wird, ist "ist fehlgeschlagen" die richtige Wahl. :)
Sternchen
3


Für die Party bin ich zu spät, allerdings ist die Verwendung von systemctl zusammen mit aktiv &&und ||dies wird im Skript nicht immer der Fall sein. Das Folgende ist eines, das ich für Tomcat verwendet habe, aber es kann in einer Methode verwendet werden, die Argumente verwendet und den Dienstnamen als Argumente übergibt, wenn Sie mehrere Dienste prüfen müssen, dies hier jedoch außerhalb des Gültigkeitsbereichs liegt.

STATUS=`systemctl is-active tomcat.service`
  if [[ ${STATUS} == 'active' ]]; then
    echo "Execute your tasks ....."
  else 
    echo " Service not running.... so exiting "  
    exit 1  
  fi

Dies ist, wie ich ausgenutzt habe ... Ich teile nur meine.

und für die Einfachheit und einfache Sachen, folgen Sie anderen hier erklärt:

systemctl -q is-active tomcat.service  && echo "Tomcat Runnung" || echo "Service is not running at all "
SAGAR Nair
quelle
Wie ist das besser als einfach if systemctl is-active --quiet tomcat.service? Ist auch [[keine Standard-Shell.
Toby Speight
@TobySpeight Du musst meinen Post ein bisschen mehr lesen, als ich in meinem Post erwähnt habe. Ich habe nie gesagt, es ist eine Standard-Shell-Verwendung. Wenn Sie eine einzelne Klammer erstellen, wird sie dann verwendet, aber das ist hier nicht möglich. Darüber hinaus erwähne ich im Folgenden die einfache Verwendung einzelner Zeilen, um dies mit &&und zu tun ||.
Sagar Nair
2

Anstatt den sed-Befehl wie in der Antwort von Oxmel zu verwenden, ist es ausreichend, ihn cut -d'=' -f 2für alle Arten von abgefragten Eigenschaften zu verwenden:

zum Beispiel:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running
Mohamed El
quelle
Das ist großartig, aber Sie müssen wirklich eine Erklärung geben, was diese Befehle bewirken.
Phill Healey
-1

Habe gerade dieses tolle kleine Drehbuch gefunden:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

Quelle

Terry
quelle
Nicht alle Dienste haben eine gleichnamige ausführbare Datei, und jeder Benutzer könnte einen Befehl ausführen, der versehentlich passt - dies ist ein Rezept für eine Katastrophe.
Toby Speight