Question Comment déterminer si un processus est en cours d'exécution ou non et l'utiliser pour créer un script shell conditionnel?


Comment puis-je déterminer si un processus est en cours d'exécution ou non et qu'un script bash exécute certains éléments en fonction de cette condition?

Par exemple:

  • si processus abc est en cours d'exécution, faites cela

  • Si ce n'est pas le cas, faites-le.


83
2018-06-29 21:53


origine


Sentez-vous important de noter qu'aucune des solutions ci-dessous ne prend en compte l'état du processus. Un commentaire sur l'un des mes questions m'a amené ici, mais un répondre sur elle m'a informé dans différents états d'un programme, comme zombie processus »(pas ce que je décrirais comme un processus" en cours d'exécution "). Une liste complète de ce que le STAT valeurs de colonne, dans la sortie de ps, indique est ici pour ceux qui sont enclins à écrire une réponse adaptée à cela, ou à modifier les leurs. - user66001
Discussion connexe: unix.stackexchange.com/questions/74185/… - blong
le meilleur moyen de vérifier le processus existe: stackoverflow.com/questions/3043978/… - Trevor Boyd Smith


Réponses:


Un script bash pour faire quelque chose comme ça ressemblerait à ceci:

#!/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

Ce script ne fait que vérifier si le programme "gedit" est en cours d'exécution.

Ou vous pouvez seulement vérifier si le programme ne fonctionne pas comme ceci:

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

138
2018-06-29 22:08



@DreadPirateShawn pouvez-vous me dire pourquoi utiliser / dev / null et pas simplement un 0? Utiliser le numéro rend le code plus lisible, au moins pour un noob (comme moi). Pas de redirection, rien - Silviu
@ Silviu hein? Googler /dev/null: "/ dev / null redirige la sortie standard de la commande vers le périphérique null, qui est un périphérique spécial qui ignore les informations qui lui sont écrites" ... en utilisant 0 redirigerait la sortie de la commande vers un fichier appelé 0. Dans ce cas, je conseillerais de devenir plus à l'aise avec > /dev/null - Vous le verrez partout, car il s’agit de la méthode standard / appropriée pour éliminer la sortie. - DreadPirateShawn
Merci beaucoup, je l'ai utilisé pour un joli petit script qui vérifie si un programme est en cours d'exécution avant son exécution. (bien que je devais l'étendre un peu car l'exécutable de Google Chrome n'a pas le même nom que la commande run, le nom de l'exécutable est simplement chrome). - Cestarian
S'il vous plaît ajouter le -x paramètre à pgrep pour qu'il recherche l'application exacte, sinon il obtiendra une fausse valeur s'il trouve la même chaîne dans le nom d'une autre application. Je viens de passer 1 heure pour le découvrir. - Thanos Apostolou
Pour vérifier si le programme ne fonctionne pas, utilisez ! pgrep - Mohammed Noureldin


Toute solution utilisant quelque chose comme ps aux | grep abc ou pgrep abc sont défectueux.

Pourquoi?

Comme vous ne vérifiez pas si un processus spécifique est en cours d'exécution, vous vérifiez si des processus sont en cours d'exécution. abc. Tout utilisateur peut facilement créer et exécuter un exécutable nommé abc (ou qui contient abc quelque part dans son nom ou ses arguments), provoquant un faux positif pour votre test. Il existe différentes options que vous pouvez appliquer à ps, grep et pgrep pour affiner la recherche, mais vous n'obtiendrez toujours pas de test fiable.

Alors, comment tester de manière fiable un certain processus en cours?

Cela dépend de ce dont vous avez besoin pour le test.

Je veux m'assurer que ce service abc est en cours d'exécution et sinon, lancez-le

C'est à cela que servent init et upstart. Ils vont démarrer le service et s'assurer que son pid est stocké dans un fichier pid. Essayez de redémarrer le service (via init ou upstart) et il vérifiera le fichier pid et le lancera s'il n'est pas là ou abandonne s'il est déjà en cours d'exécution. Ce n'est toujours pas fiable à 100%, mais c'est aussi proche que possible.

Voir Comment puis-je vérifier si mon serveur de jeu fonctionne toujours ... pour d'autres solutions.

abc est mon script. Je dois m'assurer qu'une seule instance de mon script est en cours d'exécution.

Dans ce cas, utilisez un fichier de verrouillage ou un lockdir. Par exemple.

#!/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 ...

Voir Bash FAQ 45 pour d'autres moyens de verrouillage.


32
2018-06-30 07:29



Bien que cela soit techniquement vrai, je n'ai jamais rencontré personnellement un tel problème dans la vie réelle. La plupart des programmes ne changent pas de nom d'une manière qui casse les scripts. Ainsi, pour des scripts simples, quelque chose comme pgrep ou ps est parfaitement adapté et votre approche semble exagérée. Si vous écrivez un script pour la distribution publique, vous devriez l'écrire de la manière la plus sûre possible. - Scott Severance
@ScottSeverance Programmes changer les noms n'est pas le problème; cela nécessiterait une intervention indépendamment. Ce sont les autres utilisateurs qui exécutent le même programme, ou d'autres programmes avec des noms similaires, qui provoquent soudainement des faux positifs dans le script et font donc le mauvais choix. Je préfère juste "travaux" plutôt que "principalement travaux". - geirha
Je me suis mal exprimé. Mais beaucoup d’entre nous exploitent des systèmes mono-utilisateur. Et dans une situation multi-utilisateurs, il est facile de trouver le nom d'utilisateur. - Scott Severance
Que se passe-t-il si votre script échoue pendant l'exécution et meurt avant de déverrouiller le fichier? - jp093121
@ jp093121 Le piège EXIT est déclenché à la fermeture du script. Qu'il quitte parce qu'il atteint la fin du script, une commande d'exit ou reçoit un signal (qui peut être traité), le rmla commande est exécutée. Donc, tant que le piège est terminé, le verrou doit disparaître. - geirha


C'est ce que j'utilise:

#!/bin/bash

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

En clair anglais: Si 'pgrep' renvoie 0, le processus est en cours d'exécution, sinon ce n'est pas le cas.


Lecture connexe:

Bash Scripting :: Comparaisons de chaînes

Manuels Ubuntu pgrep


17
2018-06-29 22:15



merci! J'ai essayé ça aussi ça marche parfaitement aussi :) - Nirmik
pgrep a la même "caractéristique" limite de 15 caractères précédemment mentionnée, par exemple pgrep gnome-power-manager serait également échouer - Thorsen
Assurez-vous d'utiliser les pgrep -x option: "Seuls les processus dont le nom (ou la ligne de commande si -f est spécifié) correspondent exactement au modèle." - Alastair Irvine


J'ai habituellement un pidof -x $(basename $0) sur mes scripts pour vérifier si elle est déjà en cours d'exécution.


5
2018-01-14 09:42





Riffing sur l'idée de @ rommel-cid, vous pouvez utiliser pidof avec le || (||) pour exécuter une commande si le processus n'existe pas et && pour exécuter quelque chose si le processus existe, créant ainsi une condition conditionnelle if / then / else. Par exemple, voici un processus en cours d'exécution (mon navigateur Chrome, dont le nom de processus est «chrome») et un autre testant un processus qui n'existe pas. J'ai supprimé la sortie standard en utilisant 1> / dev / null pour qu'elle n'imprime pas:

$ (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
$

1
2018-03-01 23:08





La première chose qui me vint à l'esprit pour votre problème:
ps aux | grep -i abc montrera les détails du processus s'il est en cours d'exécution. Vous pouvez faire correspondre le nombre de lignes ou le temps pour lequel il est exécuté et comparer avec zéro ou toute autre manipulation. Lorsque vous exécutez la commande ci-dessus, vous verrez au moins une ligne de sortie, c'est-à-dire des détails sur le processus créé par cette commande grep. Prenez donc soin de cela.
Cela devrait faire comme un simple hack. Mettez-le dans le script bash et voyez si c'est utile.


0
2018-06-29 22:03





En utilisant start-stop-daemon:

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

Cela fonctionne comme utilisateur normal.


0
2018-06-19 17:55