web-dev-qa-db-fra.com

Bash, comment laisser quelques processus d'arrière-plan courir mais attendre les autres?

J'ai (encore) un autre wait, &, && question de contrôle de contrôle ..

Dis que j'ai un script quelque chose comme ça où je veux faire autant de travail en même temps que possible:

# may take some hours
something InputA > IrrelevantA &
something InputB > IrrelevantB &

# may take an hour
(
   somethingElse InputA > OutputA &
   somethingElse InputB > OutputB &
)&& combine OutputA OutputB > Result

...morestuff

Question 1: Dans le script, combine attend que les processus somethingElse se terminent tant que les processus something se poursuivent?

Question 2: Si non - et je soupçonne que cela ne le fait pas - comment puis-je obtenir combine pour attendre uniquement les processus somethingElse tandis que something processus ci-dessus continue de fonctionner loin à l'arrière-plan?

11
Stephen Henderson

Dans votre exemple, la commande combine _ sera simplement exécutée dès que les Subshell quittent (et à condition que le dernier processus de référence ait été démarré sans erreur). Le sous-shell quittera immédiatement après le début des emplois car il n'y a pas de commandement wait.

Si vous souhaitez exécuter une commande basée sur la valeur de retour de deux ou plusieurs processus d'arrière-plan simultanés, je ne peux pas voir d'autre manière autre que d'utiliser des fichiers temporaires pour les valeurs de retour. C'est parce que wait _ ne peut que renvoyer la valeur de retour de n des processus qu'il attend. De plus, les processus d'arrière-plan doivent être exécutés dans des sous-vases pour obtenir leurs valeurs de retour, elles ne sont pas stockées dans des variables. Vous pourriez faire:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

tmp1=$(mktemp)
tmp2=$(mktemp)

( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!

( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!

wait "$proc1" "$proc2"

read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result

rm "$tmp1" "$tmp2"

Si vous ne vous souciez pas vraiment des valeurs de retour, vous pouvez simplement commencer les travaux normalement et utiliser wait:

something InputA >IrrelevantA &
something InputB >IrrelevantB &

somethingElse InputA >OutputA &
proc1=$!

somethingElse InputB >OutputB &
proc2=$!

wait "$proc1" "$proc2"
combine OutputA OutputB >Result
13
Graeme

Vous pouvez utiliser la commande wait:

(echo starting & sleep 10 & wait) && echo done

Vous pouvez voir la ligne "Démarrer" se déroule tout de suite, et le "fait" attend 10 secondes.

2
psusi