web-dev-qa-db-fra.com

Comment déterminer si un processus est en cours d'exécution ou non et comment 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, puis demander à un script bash d'exécuter certaines tâches en fonction de cette condition?

Par exemple:

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

  • si cela ne fonctionne pas, faites-le.

105
Nirmik

Un script bash pour faire quelque chose comme ça pourrait ressembler à ç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 seulement vérifier si le programme ne fonctionne pas comme ceci:

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

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

Pourquoi?

Étant donné que 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 qui contient abc quelque part dans son nom ou ses arguments), ce qui provoque 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 puis-je tester de manière fiable pour un certain processus en cours d'exécution?

Cela dépend de ce que vous avez besoin du test.

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

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 Comment puis-je vérifier si mon serveur de jeu est toujours en cours d'exécution ... 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 lockfile 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.

34
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:: si 'pgrep' renvoie 0, le processus est en cours d'exécution, sinon ce n'est pas le cas.


Lecture connexe:

Script Bash :: Comparaisons de chaînes

Manuels Ubuntu pgrep

18
Zuul

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.

5
Rommel Cid

Pour suivre 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 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 de processus 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
$
2
yuvilio

Aucune des solutions "simples" n'a fonctionné pour moi car le binaire que je dois vérifier n'est pas installé à l'échelle du système. Je dois donc vérifier avec le chemin, ce qui nécessite l'utilisation de l'approche ps -ef | grep:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    Nohup "$app" &> /dev/null &
fi
1
ceremcem
## 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 &)

Note: pgrep -x lxpanel ou pidof lxpanel signale toujours que lxpanel est en cours d'exécution même lorsqu'il est obsolète (zombie); donc pour obtenir un processus actif, nous devons utiliser ps et grep

0
Bach Lien

La première chose qui m'est venue à 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 office de simple bidouillage. Mettez-le dans le script bash et voyez si c'est utile.

0
drake01

Utiliser 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
Martin Monperrus

J'ai trouvé 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 fonctionnait 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:

Supposons que mon processus comporte 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
0
Wayne Workman