Bash : Tester si un processus/script est toujours actif/en cours

Comment déterminer si un script est toujours en cours d’exécution ?

Ce court article propose deux solutions simple pour déterminer si un processus est toujours en cours, sans passer par un chaînage de « ps » et de « grep » pas toujours élégants.

Utilisation du pseudo système de fichier « proc »

La première alternative consiste à tester l’existence dans « /proc » du répertoire associé au processus et dont le nom est le PID du process. Par exemple dans le shell courant :

fhh@cixi ~ $ echo $$ # PID du shell courant :
1835
fhh@cixi ~ $ ls -d /proc/$$ # dans proc :
/proc/1835
fhh@cixi ~ $ [ -d /proc/$$ ] && echo "Shell actif"
Shell actif !

À chaque instanciation d’un processus, un répertoire nommé par le PID du processus est créé dans « /proc » et y reste durant toute la vie du processus.

Voici un petit exemple de script qui ne peut être exécuté « qu’une fois à la fois » :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# Création d'un nom de fichier de vérouillage :
LOCKFILE="/run/lock/$(basename $0)" ;
# Si un fichier de lock existe ...
[ -e ${LOCKFILE} ] && {
        echo "Fichier de lock antérieur trouvé..." ;
#       Vérifions si le processus est en cours :
        [ -d /proc/$(cat ${LOCKFILE}) ] && {
#               Si oui, fin de script :
                echo "Processus encore actif. Fin." ;
                exit 0 ;
        } || {
#               Si non le fichier à été oublié. Il est supprimé :
                echo "Processus terminé. Nettoyage." ;
                rm ${LOCKFILE} ;
        }
}
# Création du fichier de lock :
echo ${$} > ${LOCKFILE} ;
# Le script :
sleep 15 ;
# Nettoyage du fichier de lock :
[ -e ${LOCKFILE} ] && rm ${LOCKFILE} ;

À l’execution, nous obtenons :

fhh@cixi ~ $ ./testpid.sh & # Premier lancement RAS :
[1] 1909
fhh@cixi ~ $ ./testpid.sh # Second appel, l’occurrence précédente est detectée : 
Fichier de lock antérieur trouvé...
Processus encore actif. Fin.
fhh@cixi ~ $ # Une fois les processus terminés...
fhh@cixi ~ $ ./testpid.sh # Lancement du script puis Ctrl+C pour le couper...
^C 
fhh@cixi ~ $ ./testpid.sh # Le fichier de lock précédent n'a pas été détruit...
Fichier de lock antérieur trouvé...
Processus terminé. Nettoyage.

Utilisation des signaux

La seconde solution est plus élégante. Elle consiste à vérifier si le processus accepte de recevoir des signaux systèmes (SIGHUP, SIGQUIT, etc) via « kill -0 PID«  (il s’agit d’un zéro). « kill » Retourne 0 si le process est actif, 1 et un message d’erreur sinon.

fhh@cixi ~ $ echo $$
1858
fhh@cixi ~ $ kill -0 $$
fhh@cixi ~ $ echo $?
0
fhh@cixi ~ $ kill -0 $$ && echo "Ce shell est actif" 
Ce shell est actif
fhh@cixi ~ $ kill -0 12000
-bash: kill: (12000) - No such process

Le script présenté ci-dessus reste le même à l’exception de la ligne 8 qui devient :

8
        kill -0 ${$} > /dev/null 2>&1 && {

Le comportement du script ne change pas…

Une réflexion au sujet de « Bash : Tester si un processus/script est toujours actif/en cours »

  1. Bonjour,
    Merci pour ce script, ça va me servir.
    Par contre, la 2ème solution pose problème. Si on arrête le script avant la fin, on ne peut plus le relancer, il croit que le processus tourne encore au lieu de nettoyer le fichier de lock et de continuer.
    Je ne saurais pas dire la raison de ce problème (pas encore assez calé sous Linux) ou si c’est lié à mon système PcDuino8 sous Linux linaro-alip 3.4.39.
    Je retiens donc la première solution.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

 

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.