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