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

90

Comment puis-je déterminer si un processus est en cours d'exécution ou non, puis qu'un script bash exécute des tâches en fonction de cette condition?

Par exemple:

  • si le processus abc est en cours d'exécution, procédez ainsi

  • s'il ne fonctionne pas, faites-le.

posée Nirmik 29.06.2012 - 23:53
la source

12 réponses

148

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

#!/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 vérifie simplement si le programme "gedit" est en cours d'exécution.

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

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi
    
réponse donnée John Vrbanac 30.06.2012 - 00:08
la source
33

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

Pourquoi?

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

Alors, comment puis-je tester de manière fiable un certain processus en cours d'exécution?

Cela dépend de la raison pour laquelle vous avez besoin du test.

Je veux m'assurer que le service abc est en cours d'exécution. Sinon, démarrez-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 pidfile. Essayez de redémarrer le service (via init ou upstart) et il vérifiera le pidfile, et le démarrera s'il n'est pas là ou annulera 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 le 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 lockfile ou un lockdir. Ex.

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

Consultez la FAQ Bash 45 pour connaître d'autres méthodes de verrouillage.

    
réponse donnée geirha 30.06.2012 - 09:29
la source
17

Voici 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: 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

    
réponse donnée Zuul 30.06.2012 - 00:15
la source
5

J'ai généralement un pidof -x $(basename $0) sur mes scripts pour vérifier s'il est déjà en cours d'exécution.

    
réponse donnée Rommel Cid 14.01.2014 - 10:42
la source
1

En vous reportant à l'idée de @rommel-cid, vous pouvez utiliser pidof avec le || (||) pour exécuter une commande si le processus n'existe pas et & & exécuter quelque chose si le processus existe, créant ainsi un conditionnel rapide if / then / else. Par exemple, voici un exemple avec un processus en cours d'exécution (mon navigateur chrome, dont le nom est "chrome") et un test pour un processus inexistant. J'ai supprimé la sortie standard en utilisant 1 > / dev / null pour qu'elle ne soit pas imprimée:

$ (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
$
    
réponse donnée yuvilio 02.03.2014 - 00:08
la source
0

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

    
réponse donnée drake01 30.06.2012 - 00:03
la source
0

Utilisation de start-stop-daemon :

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

Cela fonctionne comme un utilisateur normal.

    
réponse donnée Martin Monperrus 19.06.2015 - 19:55
la source
0

J'ai constaté que la réponse acceptée postée par @John Vrbanac ne fonctionnait pas pour moi et que la réponse postée par @geirha ne répondait pas à la question initiale.

La solution de John Vrbanac n'a pas fonctionné pour vérifier si un processus PHP était en cours d'exécution ou non pour moi, j'utilise CentOS 7.

La réponse de @ geirha s'assure seulement qu'une instance n'est pas déjà en cours d'exécution avant d'en démarrer une autre. Ce n'était pas la question initiale, la question initiale était de vérifier si un processus est en cours d'exécution ou non.

Voici ce qui a fonctionné pour moi:

Dites que mon processus avait la chaîne "Jane" dans son nom de processus. Cela va trouver si c'est en cours d'exécution ou non. Cela fonctionne pour les scripts BASH et PHP.

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi
    
réponse donnée Wayne Workman 11.11.2016 - 20:12
la source
0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

Remarque : pgrep -x lxpanel ou pidof lxpanel indique toujours que lxpanel est en cours d'exécution même s'il est obsolète (zombie); donc, pour que le processus soit actif, nous devons utiliser ps et grep

    
réponse donnée Bach Lien 23.12.2017 - 19:01
la source
-1

À partir du 23 septembre 2016, pgrep semble avoir besoin de l'option "-x" pour que le script de muru fonctionne.

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

J'ai essayé et testé le script ci-dessus sur une machine Ubuntu 16.04.1. Profitez!

    
réponse donnée dzmanto 23.09.2016 - 20:39
la source
-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid='pgrep -x ${1}'  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done
    
réponse donnée user7449824 28.01.2017 - 19:36
la source
-3

isProcessRunning () {if [$ (pidof $ 1) > / dev / null]; then retval = 'true'; sinon retval = 'false'; Fi; echo $ retval; }

isProcessRunning geany

true

    
réponse donnée Dominic 19.01.2016 - 20:37
la source

Lire d'autres questions sur les étiquettes