web-dev-qa-db-fra.com

La façon "correcte" de tester si un service s'exécute dans un script

Mon problème:

J'écris un script bash et j'aimerais vérifier si un service donné est en cours d'exécution.

Je sais comment faire cela manuellement, avec $ service [service_name] status.

Mais (surtout depuis le passage à systemd) qui imprime tout un tas de texte un peu compliqué à analyser. J'ai supposé qu'il y avait une commande faite pour les scripts avec une sortie simple ou une valeur de retour que je pouvais vérifier.

Mais googler autour ne donne qu'une tonne de "Oh, juste ps aux | grep -v grep | grep [service_name] "résultats. Cela ne peut pas être la meilleure pratique, n'est-ce pas? Et si une autre instance de cette commande est en cours d'exécution, mais pas une lancée par le script d'initialisation SysV?

Ou devrais-je simplement me taire et me salir les mains avec un petit pgrep?

126
Nick S

systemctl a un is-active sous-commande pour cela:

systemctl is-active --quiet service

sortira avec le statut zéro si service est actif, différent de zéro sinon, ce qui le rend idéal pour les scripts:

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

Si vous omettez --quiet il affichera également l'état actuel sur sa sortie standard.

Comme indiqué par don_crissti , certaines unités peuvent être actives même si rien ne fonctionne pour fournir le service: les unités marquées comme "RemainAfterExit" sont considérées comme actives si elles sortent avec succès, l'idée étant qu'elles fournissent un service qui n'a pas besoin d'un démon ( par exemple ils configurent certains aspects du système). Les unités impliquant des démons ne seront cependant actives que si le démon est toujours en cours d'exécution.

180
Stephen Kitt

systemctl possède un mode adapté aux scripts; utilisez show plutôt que status, et ajoutez le -p/--properties et --value options pour obtenir uniquement la sortie souhaitée.

Voici un exemple (d'un système Ubuntu 17.04):

$ systemctl show -p SubState --value NetworkManager
running

L'exécution (ou autre) est un SubState. Si vous voulez savoir si un service est actif, utilisez la propriété ActiveState

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

Notes du 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 "=".
40
Zanna

En complément de la réponse de Zanna, le --value option pour systemctl show a été introduit avec version 230 de systemd . Il peut donc ne pas être disponible sur certaines distributions comme Debian Jessie.

Dans ce cas, on peut émuler l'option en utilisant sed:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running
14
Oxmel


Je suis trop en retard pour la fête, mais l'utilisation de systemctl est active avec && et || à cela dans le script ne sera pas toujours le cas. Ce qui suit est celui que j'ai utilisé pour Tomcat, mais je peux l'utiliser pour prendre des arguments et passer le nom du service comme arguments si vous devez vérifier plusieurs services, mais c'est hors de portée ici.

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

C'est ainsi que je me suis servi de ... Juste partager le mien.

et pour la simplicité et les trucs faciles, suivez les autres expliqués ici:

systemctl -q is-active Tomcat.service  && \
echo "Tomcat Runnung" || \
echo "Service is not running at all "
5
SAGAR Nair

je trouve cela utile pour l'exécution en ligne de commande ou si vous faites des scripts.

Copié de @StephenKitt

Cela vérifiera si le service est en panne et effectuera un redémarrage du service

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

le || là vérifie si la valeur de retour de systemctl est différente de zéro, ce qui signifie si elle n'est pas active comme expliqué par l'auteur.

5
asterisk

Il existe de nombreuses réponses utilisant systemctl.

Vous avez également d'autres options (où $? est pratique):

  • Utilisation de la commande pidof: supposons que j'essaie de savoir si redis-server est en cours d'exécution. Premier numéro pidof redis-server puis vérifiez la valeur de $? Vous trouverez 0 s'il était en cours d'exécution; non nul sinon.
  • Solution spécifique au service: si le service fournit un moyen de vérifier si le service est en cours d'exécution, vous pouvez l'utiliser. Pour le redis-service exemple, si le service est en cours d'exécution, nous obtiendrons une réponse PONG pour redis-cli ping commande. Après avoir émis redis-cli ping, Je vérifierais $? et s'il vaut 0, le service est en cours d'exécution.
2
Tuhin Paul

Au lieu d'utiliser la commande sed comme dans la réponse d'Oxmel, il suffit d'utiliser cut -d'=' -f 2 pour toutes sortes de propriétés interrogées:

par exemple:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running
2
Mauri

Fonctionne également pour un système d'exploitation non système.

Qu'en est-il de ps -C service-name? vérifier $? pour réponse. Si 0 ça fonctionne, si 1, il ne fonctionne pas.

Exemple:

ps -C privoxy && echo running

La version silencieuse:

ps -C privoxy 1>/dev/null && echo running

Avertissement :

J'ai remarqué que les noms de service de plus de 14 caractères peuvent donner un faux positif.

Voir aussi le commentaire de '' Nick S ''.

Exemple:

Montre correctement en cours d'exécution:

$ ps -C notification-daemon
  PID TTY          TIME CMD
 7418 ?        00:00:04 notification-da

Affiche incorrectement en cours d'exécution:

$ ps -C notification-daemon-fake
  PID TTY          TIME CMD
 7418 ?        00:00:04 notification-da

Affiche correctement ne fonctionne pas car moins de 14 caractères:

$ ps -C notification
  PID TTY          TIME CMD

J'ai obtenu cette réponse de ici .

0
ajnabi