web-dev-qa-db-fra.com

Commande Linux/Unix pour déterminer si le processus est en cours d'exécution?

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?

86
Highway of Life

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:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm

158
Caleb Gray

Vous devriez connaître le PID!

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.

Comment déterminer si le processus est en cours d'exécution (par pid)

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.

24
peterh

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.

13
Frédéric Hamidi

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
6
Pawel Solarski

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:

  • SunOS 5.10 [D'où le PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Darwin 11.2.0
  • FreeBSD 9.0-STABLE
  • Red Hat Enterprise Linux ES version 4 
  • Red Hat Enterprise Linux Server version 5
6
Johnsyweb

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"
5
gletscher

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,...>.

5
Tatjana Heuser

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?

3
olibre

Vous devez connaître le PID de votre processus.

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.

1
icarito

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.

0
Jeff Luyet

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:

  1. -m1 - arrête le processus lors du premier match
  2. "mysqld $ | httpd $" - grep correspondra aux lignes qui se sont terminées sur mysqld OR httpd
  3. / proc/[0-9] * - bash correspondra à la ligne commençant par un nombre quelconque
  4. cut - il suffit de scinder la sortie par le délimiteur '/' et d'extraire le champ 3
0
Tom Lime

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"
0
jarno

Voici ma version. Caractéristiques:

  • vérifie le nom exact du programme (premier argument de la fonction). la recherche sur "mysql" ne correspond pas à l'exécution de "mysqld"
  • recherche les arguments du programme (second argument de la fonction)

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
0
Raigedas