Avec bash
, vous aurez cette garantie à moins que vous n'ayez commencé un autre travail en arrière-plan (et sachez que les travaux en arrière-plan peuvent être démarrés avec &
mais aussi avec coproc
et avec la substitution de processus) entre le foo &
et le wait
.
POSIX requiert qu'un shell se souvienne de l'état de sortie d'au moins 25 tâches après leur disparition , mais s'en bash
souvient bien plus que cela.
Maintenant, si vous le faites:
foo & pid=$!
...
bar &
wait "$pid"
Vous n'avez aucune garantie qui bar
ne recevra pas le même pid que foo
(s'il foo
a pris fin au moment où bar
commence), donc même si c'est peu probable, il wait "$pid"
peut vous donner le statut de sortie de bar
.
Vous pouvez le reproduire avec:
bash -c '(exit 12; foo) & pid=$!
while : bar & [ "$pid" != "$!" ]; do :;done
wait "$pid"; echo "$?"'
qui vous donnera (éventuellement) 0
au lieu de 12
.
Pour éviter le problème, une façon serait de l'écrire comme suit:
{
foo_pid=$!
while ps -p "$foo_pid"
do
ping -c 1 localhost
done
bar &
...
read <&3 ret
if [ "$ret" = 0 ]; then
echo foo was sucessful.
fi
} 3< <(foo > logfile 2>&1; echo "$?")
Stéphane Chazelas
la source
wait
ne fonctionne pas. Le processus est collecté et l'état de sortie supprimé juste avant que l'invite ne s'affiche (par défaut).wait %1
échoue avec «aucun travail» car le processus d'arrière-plan est collecté immédiatement après la fin du «sommeil 5».%1
à la place de$!
.bash -c '(sleep 1;exit 5) & sleep 2; wait %1; echo $?'
(donc non interactif également) ne parvient pas à obtenir le statut de sortie de ce travail mort. Cela ressemble à un bug.set +e
. Il semble que laset -e
fonction de bash tue le script dès qu'un mauvais code de sortie est généré parwait
Je crois que votre hypothèse est correcte. Voici un extrait de l'
man bash
attente des processus d'arrière-plan.Alors peut-être devriez-vous vérifier 127
Il y a une question similaire avec une réponse complètement différente de celle qui pourrait aider.
Le script Bash attend les processus et obtient le code retour
modifier 1
Inspiré par les commentaires et les réponses de @ Stephane, j'ai développé son script. Je peux démarrer environ 34 processus d'arrière-plan avant qu'il ne commence à perdre sa trace.
tback
sur mon système produit
la source
bash -c '(exit 12) & sleep 1; wait "$!"; echo "$?"'
bash
piste lâche (même après avoir commencé des milliers d'emplois), mon exemple démontrait que le pid était réutilisé, ce qui peut être ce que vous avez également observé dans votre cas.