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…

Laisser un commentaire

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