J'ai besoin d'une commande Shell/bash indépendante de la plate-forme (Linux/Unix | OSX) qui déterminera si un processus spécifique est en cours d'exécution. par exemple. mysqld
, httpd
... Quel est le moyen le plus simple de procéder?
Bien que pidof
et pgrep
soient d'excellents outils pour déterminer ce qui est en cours d'exécution, ils sont malheureusement indisponibles sur certains systèmes d'exploitation. Un sûr échec serait d'utiliser les éléments suivants: ps cax | grep command
La sortie sur Gentoo Linux:
14484? S 0:00 Apache2 14667? S 0:00 Apache2 19620? Sl 0:00 Apache2 21132? Ss 0:04 Apache2
La sortie sur OS X:
42582 ?? Z 0: 00,00 (client) 46529 ?? Z 0: 00,00 (client) 46539 ?? Z 0: 00,00 (client) 46547 ?? Z 0: 00,00 (client) 46586 ?? Z 0: 00,00 (client) 46594 ?? Z 0: 00,00 (smbclient)
Sous Linux et OS X, grep renvoie un code de sortie, ce qui permet de vérifier facilement si le processus a été trouvé ou non:
#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
De plus, si vous voulez la liste des PID, vous pouvez facilement les grep aussi:
ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
Cette approche convient à l'écriture d'un simple test de chaîne vide, puis même à une itération à travers les PID découverts.
#!/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
Vous pouvez le tester en l'enregistrant dans un fichier (nommé "en cours d'exécution") doté d'autorisations d'exécution (chmod + x en cours d'exécution) et en l'exécutant à l'aide du paramètre: ./running "httpd"
#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
ATTENTION!!!
N'oubliez pas que vous analysez simplement la sortie de ps ax
, ce qui signifie que, comme le montre la sortie Linux, il ne s'agit pas simplement d'une correspondance sur des processus, mais également des arguments transmis à ce programme. Je recommande fortement d’être aussi précis que possible lors de l’utilisation de cette méthode (par exemple, ./running "mysql"
correspondra également aux processus 'mysqld'). Je recommande fortement d'utiliser which
pour vérifier si le chemin est complet.
Références:
Trouver un processus en essayant de faire une sorte de reconnaissance de modèle sur les arguments de processus (comme pgrep "mysqld"
) est une stratégie qui est vouée à l’échec tôt ou tard. Que faire si vous avez deux mysqld en cours d'exécution? Oubliez cette approche. Vous pouvez le faire correctement temporairement et cela peut fonctionner pendant un an ou deux, mais il se produit alors quelque chose auquel vous n'avez pas pensé.
Seul l'ID de processus (pid) est vraiment unique.
Stockez toujours le pid lorsque vous lancez quelque chose en arrière-plan. En Bash, cela peut être fait avec la variable $!
Bash. Vous vous éviterez SO beaucoup de peine en le faisant.
Alors maintenant, la question est de savoir comment savoir si un pid est en cours d'exécution.
Faites simplement:
ps -o pid = -p <pid>
C'est POSIX et donc portable. Il renverra le pid lui-même si le processus est en cours d'exécution ou rien si le processus n'est pas en cours d'exécution. À proprement parler, la commande renverra une seule colonne, la variable pid
, mais comme nous l’avons donné comme en-tête de titre vide (le contenu précédant immédiatement le signe égal) et qu’il s’agit de la seule colonne demandée, la commande ps n’utilisera pas d’entête . C'est ce que nous voulons, car cela facilite l'analyse.
Cela fonctionnera sous Linux, BSD, Solaris, etc.
Une autre stratégie consisterait à tester la valeur de sortie de la commande ps
ci-dessus. Il doit être égal à zéro si le processus est en cours d'exécution et non nul s'il ne l'est pas. La spécification POSIX indique que ps
doit quitter> 0 si une erreur s'est produite, mais je ne vois pas très bien ce qui constitue une "erreur". Par conséquent, je n’utilise pas personnellement cette stratégie, bien que je sois à peu près certaine que cela fonctionnera également sur toutes les plateformes Unix/Linux.
Sur la plupart des distributions Linux, vous pouvez utiliser pidof
(8).
Il affichera les identifiants de processus de toutes les instances en cours d'exécution des processus spécifiés ou rien si aucune instance n'est en cours d'exécution.
Par exemple, sur mon système (j'ai quatre instances de bash
et une instance de remmina
en cours d'exécution):
$ pidof bash remmina
6148 6147 6144 5603 21598
Sur d'autres Unices, pgrep
ou une combinaison de ps
et grep
obtiendra le même résultat, comme d'autres l'ont souligné à juste titre.
Le plus simple est d’utiliser ps et 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
Si votre commande a des arguments de commande, vous pouvez également ajouter plus de 'grep cmd_arg1' après 'grep $ command' pour filtrer les autres processus possibles qui ne vous intéressent pas.
Exemple: montre-moi s'il existe un processus Java avec l'argument fourni:
-Djava.util.logging.config.file = logging.properties
est en cours d'exécution
ps ax | grep -v grep | grep Java | grep Java.util.logging.config.file=logging.properties | wc -l
Cela devrait fonctionner sur la plupart des versions d'Unix, BSD et Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Testé sur:
PATH=...
]En rassemblant les différentes suggestions, la version la plus propre que j'ai pu inventer (sans le grep non fiable qui déclenche des parties de mots) est la suivante:
kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
kill -0 ne tue pas le processus, mais vérifie s'il existe, puis renvoie true. Si vous n'avez pas pidof sur votre système, stockez le pid au lancement du processus:
$ mysql &
$ echo $! > pid_stored
puis dans le script:
kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"
Juste un ajout mineur: si vous ajoutez le drapeau -c
à ps, vous n'avez pas besoin de supprimer la ligne contenant le processus grep avec grep -v
après. C'est à dire.
ps acux | grep cron
est tout ce que vous avez besoin de taper sur un système bsd-ish (cela inclut MacOSX). Vous pouvez laisser le -u
loin si vous avez besoin de moins d’informations.
Sur un système où la génétique de la commande native ps
pointe vers SysV, vous utiliseriez
ps -e |grep cron
ou
ps -el |grep cron
pour une liste contenant plus que simplement pid et nom du processus. Vous pouvez bien entendu sélectionner les champs spécifiques à imprimer à l'aide de l'option -o <field,field,...>
.
J'utilise pgrep -l httpd
mais je ne suis pas sûr qu'il soit présent sur une plate-forme quelconque ...
Qui peut confirmer sur OSX?
Lorsque vous le lancez, son PID sera enregistré dans la variable $!
. Enregistrez ce PID dans un fichier.
Ensuite, vous devrez vérifier si ce PID correspond à un processus en cours. Voici un script complet de squelette:
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
Basé sur la réponse de peterh
. L'astuce pour savoir si un PID donné est en cours d'exécution est dans l'instruction ps -o pid= -p $PID
.
Aucune des réponses n'a fonctionné pour moi, alors voici la mienne:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
Explication:
|tr -d '\n'
Cela supprime le retour chariot créé par le terminal. Le reste peut être expliqué par this post.
Cette approche peut être utilisée dans le cas où les commandes 'ps', 'pidof' et rest ne sont pas disponibles . Personnellement, j'utilise procfs très fréquemment dans mes outils/scripts/programmes.
egrep -m1 "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3
Petite explication de ce qui se passe:
Ceci affiche le nombre de processus dont le nom de base est "chrome-browser":
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"
Si cela affiche "0", le processus n'est pas en cours d'exécution. La commande suppose que le chemin du processus ne contient pas d'espace de rupture. Je n'ai pas testé cela avec des processus suspendus ou des processus zombies.
Testé en utilisant gwak
comme alternative awk
sous Linux.
Voici une solution plus polyvalente avec quelques exemples d'utilisation:
#!/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"
Voici ma version. Caractéristiques:
scénario:
#!/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