J'ai un script bash simple qui démarre deux serveurs:
#!/bin/bash
(cd ./frontend && gulp serve) & (cd ./backend && gulp serve --verbose)
Si la deuxième commande se termine, il semble que la première commande continue de s'exécuter.
Comment puis-je changer cela de sorte que si l'une des commandes se termine, l'autre se termine?
Notez que nous n'avons pas besoin de vérifier les niveaux d'erreur des processus d'arrière-plan, juste s'ils se sont arrêtés.
bash
shell-script
background-process
blah238
la source
la source
gulp ./fronend/serve && gulp ./backend/serve --verbose
?serve
est un argument, pas un fichier, donc le répertoire courant doit être défini.Réponses:
Cela démarre les deux processus, attend le premier qui se termine puis tue l'autre:
Comment ça fonctionne
Début:
Les deux commandes ci-dessus démarrent les deux processus en arrière-plan.
Attendez
Cela attend la fin de l'un ou l'autre des travaux en arrière-plan.
En raison de l'
-n
option, cela nécessite bash 4.3 ou mieux.Tuer
Cela tue tout travail dont le processus actuel est le parent. En d'autres termes, cela tue tout processus d'arrière-plan toujours en cours d'exécution.
Si votre système n'en a pas
pkill
, essayez de remplacer cette ligne par:ce qui tue également le groupe de processus actuel .
Exemple facilement testable
En changeant le script, nous pouvons le tester même sans
gulp
installé:Le script ci-dessus peut être exécuté en tant que
bash script.sh 1 3
et le premier processus se termine en premier. Alternativement, on peut l'exécuter en tant quebash script.sh 3 1
et le deuxième processus se terminera en premier. Dans les deux cas, on peut voir que cela fonctionne comme souhaité.la source
bash
prennent pas en charge l'-n
option de lawait
commande. (2) Je suis d'accord à 100% avec la première phrase - votre solution démarre deux processus, attend que le premier se termine, puis tue l'autre. Mais la question dit «… si l'une des erreurs de commande , l'autre est terminée?» Je pense que votre solution n'est pas celle que souhaite le PO. (3) Pourquoi avez-vous changé(…) &
pour{ …; } &
? La&
force la liste (commande de groupe) à s'exécuter dans un sous-shell de toute façon. À mon humble avis, vous avez ajouté des caractères et éventuellement introduit de la confusion (j'ai dû le regarder deux fois pour le comprendre) sans aucun avantage.pkill
n'est pas disponible pour moi maiskill 0
semble avoir le même effet. J'ai également mis à jour mon environnement Git pour Windows et cela semblewait -n
fonctionner maintenant, donc j'accepte cette réponse.kill
. la documentation de mon système ne le mentionne pas. Cependant,kill 0
ça marche quand même. Bonne trouvaille!C'est délicat. Voici ce que j'ai imaginé; il peut être possible de le simplifier / rationaliser:
while true; do sleep 42; done &
) qui s'endort / s'arrête pour toujours. Si vous êtes sûr que vos deux commandes se termineront dans un certain laps de temps (par exemple, une heure), vous pouvez changer cela en un seul sommeil qui dépassera cela (par exemple,sleep 3600
). Vous pouvez ensuite modifier la logique suivante pour l'utiliser comme délai d'expiration; c'est-à-dire, tuez les processus s'ils sont toujours en cours d'exécution après ce temps. (Notez que le script ci-dessus ne fait actuellement pas cela.)./
pourcd
.command & echo "$!" > somewhere; wait "$!"
est une construction délicate qui démarre un processus de manière asynchrone, capture son PID, puis l'attend; ce qui en fait une sorte de processus de premier plan (synchrone). Mais cela se produit dans une(…)
liste qui est en arrière-plan dans son intégralité, de sorte que lesgulp
processus s'exécutent de manière asynchrone.gulp
processus terminé, écrivez son état dans un fichier temporaire et supprimez le processus «toujours en sommeil».sleep 1
pour se protéger contre une condition de concurrence critique où le premier processus d'arrière-plan meurt avant que le second n'ait la possibilité d'écrire son PID dans le fichier.gulp
processus, comme indiqué ci-dessus.la source
Pour être complet, voici ce que j'ai fini par utiliser:
Cela fonctionne pour moi sur Git pour Windows 2.5.3 64 bits. Les versions plus anciennes peuvent ne pas accepter l'
-n
optionwait
.la source
Sur mon système (Centos),
wait
n'a pas-n
donc j'ai fait ceci:Cela n'attend pas "non plus", attend plutôt le premier. Mais cela peut toujours aider si vous savez quel serveur sera arrêté en premier.
la source
wait
l'-n
option soit ou non dépend du shell que vous utilisez, pas de la distribution Linux.