Existe-t-il une fonctionnalité intégrée dans Bash pour attendre la fin d'un processus?
La wait
commande permet seulement d'attendre la fin des processus enfants. Je voudrais savoir s'il existe un moyen d'attendre la fin d'un processus avant de procéder à 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
Réponses:
Attendre la fin de tout processus
Linux:
Darwin (nécessite d'
$pid
avoir des fichiers ouverts):Avec timeout (secondes)
Linux:
Darwin (nécessite d'
$pid
avoir des fichiers ouverts):la source
tail
ferait cela.tail
fonctionne sous le capot en interrogeantkill(pid, SIG_0)
un processus (découvert en utilisantstrace
).+r 1
dire le timeout, je recherche personnellement une solution pour MacOS qui n'utilise pas d'interrogation.tail
a la lignekill (pid, 0) != 0 && errno != EPERM
.caffeinate -w $pid
fera l'affaire.Il n'y a pas de builtin. À utiliser
kill -0
en boucle pour une solution viable:Ou comme oneliner plus simple pour une utilisation simple et unique:
Comme l'ont noté plusieurs commentateurs, si vous souhaitez attendre des processus auxquels vous n'avez pas le privilège d'envoyer des signaux, vous avez trouvé un autre moyen de détecter si le processus est en cours d'exécution pour remplacer l'
kill -0 $pid
appel. Sous Linux,test -d "/proc/$pid"
fonctionne, sur d'autres systèmes, vous devrez peut-être utiliserpgrep
(si disponible) ou quelque chose du genreps | grep "^$pid "
.la source
sleep 0.5
, le processus avec$pid
peut mourir et un autre processus peut être créé avec le même$pid
. Et nous finirons par attendre 2 processus différents (voire plus) avec le même$pid
.J'ai trouvé que "kill -0" ne fonctionne pas si le processus appartient à root (ou autre), j'ai donc utilisé pgrep et j'ai trouvé:
Cela aurait l'inconvénient de correspondre probablement aux processus zombies.
la source
kill(pid, sig=0)
échoue si le processus appelant n'a pas le privilège de tuer. Ainsi / bin / kill -0 et "kill -0" (bash intégré) échouent également dans les mêmes conditions.Cette boucle de script bash se termine si le processus n'existe pas ou si c'est un zombie.
EDIT : Le script ci-dessus a été donné ci-dessous par Rockallite . Merci!
Ma réponse originale ci-dessous fonctionne pour Linux, en s'appuyant sur
procfs
ie/proc/
. Je ne connais pas sa portabilité:Ce n'est pas limité au shell, mais les OS eux-mêmes n'ont pas d'appels système pour surveiller l'arrêt des processus non enfants.
la source
grep /proc/$PID/status
de guillemets doubles (bash: test: argument expected
)while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do sleep 1; done
ps
, ni l'un-p
ni l' autre ous=
sont pris en chargeFreeBSD et Solaris ont cet
pwait(1)
utilitaire pratique , qui fait exactement ce que vous voulez.Je crois que d'autres systèmes d'exploitation modernes ont également les appels système nécessaires (MacOS, par exemple, implémente BSD
kqueue
), mais tous ne le rendent pas disponible à partir de la ligne de commande.la source
> BSD and Solaris
: Inspecter les trois grands BSD qui me viennent à l'esprit; ni OpenBSD ni NetBSD n'ont cette fonction (dans leurs pages de manuel), seul FreeBSD le fait, comme vous pouvez facilement le vérifier sur man.openbsd.org .kqueue
, donc compiler FreeBSDpwait(1)
serait trivial, cependant. Pourquoi les autres BSD n'importent-ils pas la fonctionnalité qui m'échappe ...plink me@oracle box -pw redacted "pwait 6998";email -b -s "It's done" etc
m'a juste permis de rentrer à la maison maintenant au lieu de quelques heures.Depuis la page de manuel bash
la source
wait
sans argument bloquera le processus jusqu'à ce que tous les processus enfants se terminent. Honnêtement, je ne vois aucun intérêt à attendre un processus car il y a toujours des processus système en cours.sleep 1000
ctrl-z
wait [sleep pid]
retourne immédiatementToutes ces solutions sont testées dans Ubuntu 14.04:
Solution 1 (en utilisant la commande ps): Juste pour ajouter à la réponse de Pierz, je suggérerais:
Dans ce cas,
grep -vw grep
garantit que grep correspond uniquement à nom_processus et non à grep lui-même. Il a l'avantage de prendre en charge les cas où le process_name n'est pas à la fin d'une ligne àps axg
.Solution 2 (en utilisant la commande supérieure et le nom du processus):
Remplacer
process_name
par le nom du processus qui apparaît danstop -n 1 -b
. Veuillez conserver les guillemets.Pour voir la liste des processus que vous attendez qu'ils soient terminés, vous pouvez exécuter:
Solution 3 (en utilisant la commande supérieure et l'ID de processus):
Remplacez-le
process_id
par l'ID de processus de votre programme.la source
grep -v grep
pipeline est un anti-modèle massif, et cela présuppose que vous n'avez pas de processus sans rapport avec le même nom. Si vous connaissez plutôt les PID, cela pourrait être adapté à une solution fonctionnant correctement.-w
pour éviter le problèmegrep -v grep
dans une certaine mesure . J'ai également ajouté deux autres solutions basées sur votre commentaire.D'accord, il semble donc que la réponse soit - non, il n'y a pas d'outil intégré.
Après avoir réglé
/proc/sys/kernel/yama/ptrace_scope
sur0
, il est possible d'utiliser lestrace
programme. D'autres commutateurs peuvent être utilisés pour le rendre silencieux, afin qu'il attende vraiment passivement:la source
Operation not permitted
pour la seconde instance de strace); pouvez-vous le confirmer?(...)"tracee" always means "(one) thread"
(et je confirme l'erreur que vous mentionnez). Pour laisser plus de processus attendre de cette façon, vous devez créer une chaîne.Solution de blocage
Utilisez le
wait
dans une boucle, pour attendre la fin de tous les processus:Cette fonction se terminera immédiatement, lorsque tous les processus seront terminés. C'est la solution la plus efficace.
Solution non bloquante
Utilisez le
kill -0
dans une boucle, pour attendre la fin de tous les processus + faire quoi que ce soit entre les vérifications:Le temps de réaction a diminué avec le
sleep
temps, car il faut éviter une utilisation élevée du processeur.Un usage réaliste:
En attente de la fin de tous les processus + informer l'utilisateur de tous les PID en cours d'exécution.
Remarques
Ces fonctions obtiennent des PID via des arguments en
$@
tant que tableau BASH.la source
J'ai eu le même problème, j'ai résolu le problème en tuant le processus, puis en attendant que chaque processus se termine en utilisant le système de fichiers PROC:
la source
Il n'y a pas de fonction intégrée pour attendre la fin d'un processus.
Vous pouvez envoyer
kill -0
à n'importe quel PID trouvé, afin de ne pas être déconcerté par les zombies et les éléments qui seront toujours visibles dansps
(tout en récupérant la liste PID en utilisantps
).la source
Utilisez inotifywait pour surveiller certains fichiers qui se ferment lorsque votre processus se termine. Exemple (sous Linux):
-e spécifie l'événement à attendre, -q signifie une sortie minimale uniquement à la fin. Dans ce cas, ce sera:
Une seule commande wait peut être utilisée pour attendre plusieurs processus:
La chaîne de sortie de inotifywait vous indiquera quel processus s'est terminé. Cela ne fonctionne qu'avec des fichiers 'réels', pas avec quelque chose dans / proc /
la source
Sur un système comme OSX, vous n'avez peut-être pas pgrep, vous pouvez donc essayer cette approche, lorsque vous recherchez des processus par nom:
Le
$
symbole à la fin du nom du processus garantit que grep correspond uniquement à nom_processus à la fin de la ligne dans la sortie ps et non à lui-même.la source
/dev/null
,-q
doit être utilisé avecgrep
. Une autre instance du processus a peut-être commencé pendant que votre boucle dormait et vous ne saurez jamais ...-q
suggestion soit valide, comme je l'ai mentionné dans ma réponse spécifiquement, la terminaison$
signifie que grep ne correspondra pas au nom «quelque part dans la ligne de commande» ni ne correspondra à lui-même. Avez-vous réellement essayé sur OSX?La solution de Rauno Palosaari pour
Timeout in Seconds
Darwin
, est une excellente solution de contournement pour un système d'exploitation de type UNIX qui n'a pas GNUtail
(ce n'est pas spécifique àDarwin
). Mais, selon l'âge du système d'exploitation de type UNIX, la ligne de commande proposée est plus complexe que nécessaire et peut échouer:Sur au moins un ancien UNIX, l'
lsof
argument+r 1m%s
échoue (même pour un super-utilisateur):Le
m%s
est une spécification de format de sortie. Un post-processeur plus simple n'en a pas besoin. Par exemple, la commande suivante attend le PID 5959 pendant cinq secondes maximum:Dans cet exemple, si le PID 5959 sort de lui-même avant la fin des cinq secondes,
${?}
est0
. Sinon${?}
revient1
après cinq secondes.Il peut être intéressant de noter expressément que dans
+r 1
, le1
est l'intervalle d'interrogation (en secondes), il peut donc être modifié en fonction de la situation.la source