199 votes

Attendre la fin d'un processus

Existe-t-il une fonctionnalité intégrée à Bash pour attendre la fin d'un processus ?

El wait ne permet que d'attendre la fin des processus enfants. J'aimerais savoir s'il existe un moyen d'attendre qu'un processus se termine avant de poursuivre dans un script.

Une façon mécanique de le faire est la suivante mais j'aimerais savoir s'il existe une fonctionnalité intégrée dans Bash.

while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done

4 votes

Laissez-moi vous donner deux avertissements : 1. Comme a souligné ci-dessous por mp3foley La commande "kill -0" ne fonctionne pas toujours sous POSIX. 2. Vous voulez probablement aussi vous assurer que le processus n'est pas un zombie, qui est virtuellement un processus terminé. Voir Commentaire de mp3foley y mine pour les détails.

2 votes

Une autre mise en garde ( a souligné à l'origine por ks1322 ci-dessous) : Utiliser un PID autre qu'un processus enfant n'est pas robuste. Si vous voulez un moyen sûr, utilisez par exemple IPC.

92voto

Teddy Points 3250

Il n'y a pas de module intégré. Utilisez kill -0 dans une boucle pour une solution viable :

anywait(){

    for pid in "$@"; do
        while kill -0 "$pid"; do
            sleep 0.5
        done
    done
}

Ou comme un oneliner plus simple pour un usage unique :

while kill -0 PIDS 2> /dev/null; do sleep 1; done;

Comme l'ont noté plusieurs commentateurs, si vous voulez attendre des processus auxquels vous n'avez pas le privilège d'envoyer des signaux, vous devez trouver un autre moyen de détecter si le processus est en cours d'exécution pour remplacer l'option kill -0 $pid appel. Sous Linux, test -d "/proc/$pid" fonctionne, sur d'autres systèmes vous devrez peut-être utiliser pgrep (si disponible) ou quelque chose comme ps | grep "^$pid " .

0 votes

Je n'ai jamais trouvé mieux. Vous pouvez ajouter un paramètre de timeout qui tue -15 puis tue -9 si le processus se bloque ...

0 votes

Mieux encore, tuer -15, tuer -2, tuer -1, puis peut-être tuer -9.

2 votes

Attention : Cela ne fonctionne pas toujours, car a souligné ci-dessous por mp3foley . Voir ce commentaire et mine pour les détails.

56voto

mp3foley Points 173

J'ai découvert que "kill -0" ne fonctionne pas si le processus est possédé par Root (ou autre), alors j'ai utilisé pgrep et j'ai trouvé :

while pgrep -u root process_name > /dev/null; do sleep 1; done

Cela aurait l'inconvénient de faire correspondre probablement des processus zombies.

2 votes

Bonne observation. Dans POSIX, l'appel système kill(pid, sig=0) échoue si le processus appelant n'a pas le privilège de tuer. Ainsi, /bin/kill -0 et "kill -0" (intégré à bash) échouent également dans la même condition.

32voto

teika kazura Points 518

Cette boucle bash script se termine si le processus n'existe pas, ou si c'est un zombie.

PID=<pid to watch>
while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do
    sleep 1
done

EDIT : Le script ci-dessus était donné ci-dessous par Rockallite . Merci !

Ma réponse originale ci-dessous fonctionne pour Linux, en s'appuyant sur les éléments suivants procfs c'est-à-dire /proc/ . Je ne connais pas sa portabilité :

while [[ ( -d /proc/$PID ) && ( -z `grep zombie /proc/$PID/status` ) ]]; do
    sleep 1
done

Ce n'est pas limité au shell, mais les systèmes d'exploitation eux-mêmes n'ont pas d'appels système pour surveiller la fin des processus non enfants.

1 votes

Joli coup. Bien que je doive entourer grep /proc/$PID/status avec des guillemets doubles ( bash: test: argument expected )

0 votes

Hum ... je viens de réessayer et ça a marché. Je suppose que j'ai fait quelque chose de mal la dernière fois.

8 votes

Ou while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do sleep 1; done

11voto

Charlweed Points 217

Extrait de la page de manuel de bash

   wait [n ...]
          Wait for each specified process and return its termination  status
          Each  n  may be a process ID or a job specification; if a
          job spec is given, all processes  in  that  job's  pipeline  are
          waited  for.  If n is not given, all currently active child processes
          are waited for, and the return  status  is  zero.   If  n
          specifies  a  non-existent  process or job, the return status is
          127.  Otherwise, the return status is the  exit  status  of  the
          last process or job waited for.

60 votes

C'est vrai, mais il ne peut attendre que l'enfant du shell actuel. Vous ne pouvez pas attendre cualquier processus.

0 votes

@gumik : "Si n n'est pas donné, tous les processus enfants actuellement actifs sont attendus" . Cela fonctionne parfaitement.. wait sans argument bloquera le processus jusqu'à ce que tout enfant finition des processus. Honnêtement, je ne vois pas l'intérêt d'attendre que cualquier puisqu'il y a toujours des processus système en cours.

1 votes

@coderofsalvation ( sleep 10 & sleep 3 & wait ) prend 10 secondes pour revenir : wait sans args bloquera jusqu'à ce que TOUS les processus enfants se terminent. L'OP veut être notifié lorsque le premier processus enfant (ou nommé) se termine.

6voto

emu Points 296

Ok, donc il semble que la réponse soit -- non, il n'y a pas d'outil intégré.

Après le réglage /proc/sys/kernel/yama/ptrace_scope a 0 il est possible d'utiliser le strace programme. D'autres interrupteurs peuvent être utilisés pour le rendre silencieux, afin qu'il attende vraiment passivement :

strace -qqe '' -p <PID>

1 votes

Joli coup ! Il semble cependant qu'il ne soit pas possible de s'attacher à un PID donné à partir de deux endroits différents (j'obtiens Operation not permitted pour la deuxième instance de strace) ; pouvez-vous le confirmer ?

0 votes

@eudoxos Oui, la page de manuel de ptrace dit : (...)"tracee" always means "(one) thread" (et je confirme l'erreur que vous mentionnez). Pour laisser plus de processus attendre de cette façon, il faudrait faire une chaîne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X