2 votes

Comment éviter de tuer le mauvais processus dans un script bash?

Je suis en train d'écrire un script bash qui lance quelques processus enfants, et qui sera exécuté par une tâche cron toutes les heures. Il lance en réalité une commande rsync vers un serveur distant, ainsi que la connexion ssh associée.

Si la commande rsync ou le script prend trop de temps, je voudrais le arrêter ainsi que ses processus enfants, mais lui donner d'abord une période de grâce. Le script s'exécute toutes les heures, mais les 2 tentatives suivantes vérifieront qu'une instance précédente du script est en cours d'exécution et se termineront avant de tenter de commencer un transfert. La troisième tentative suivante tuera l'original, toujours en cours, avant de commencer un nouveau transfert.

J'ai décidé de contrôler cela en écrivant dans un fichier PID, la première instance écrit son PID dans le fichier, les deux tentatives suivantes écrivent leur PID dans le fichier avant de se terminer. La troisième tentative tue la première, ensuite écrase le fichier PID avec le nouveau PID. Tout achèvement réussi efface le fichier PID. Pour tuer tous les enfants, j'ai décidé d'utiliser le PGID de l'instance originale du script que j'obtiens avec :

previous_pid=$(head -n1 "$pid_file")
previous_groupid=$(ps -hp "$previous_pid" -o pgid:1)

Ensuite le tuer avec:

kill -- -"$previous_pid"

Ma préoccupation est qu'il puisse y avoir une condition où le script original est mort sans nettoyer le fichier PID, et ce PID est réutilisé, réutilisant également le PGID, alors je finirai par tuer un processus complètement sans rapport. Comment puis-je éviter cela?

3voto

muru Points 180007

Obtenez le script pour s'auto-détruire. Par exemple, insérez quelque chose comme ceci au début de votre script:

kill_myself () {
    while sleep 1
    do
        if [[ -f /tmp/kill-myself ]]
        then
            rm /tmp/kill-myself
            kill -- -$1
        fi
    done
}

kill_myself $$ &

Maintenant, lorsque le moment viendra:

touch /tmp/kill-myself

Vous pourriez personnaliser ceci, de sorte que chaque instance du script ait son propre fichier d'arrêt, que vous enregistriez quelque part. Ensuite, vous utiliserez ce fichier pour tuer cette instance spécifique du script.


Une autre façon: Vous pourriez probablement utiliser pgrep/pkill pour une correspondance plus fine. Ils peuvent lire à partir d'un fichier pid, faire correspondre le nom de la commande et les arguments, etc.

Quelque chose comme ce qui suit tuera uniquement les processus ayant le même nom que votre script (en supposant que vous l'avez appelé nom-du-script ou /chemin/vers/nom-du-script):

pkill -g "$previous_groupid" nom-du-script

Ceci ne fonctionnera pas si vous faites bash nom-du-script. Ou simplement pour tuer la commande rsync, qui devrait probablement faire sortir votre script après cela:

pkill -g "$previous_groupid" rsync

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X