Je veux exécuter deux commands simultanément dans bash sur une machine Linux. Par conséquent, dans mon script ./execute.sh
bash, j'ai mis:
command 1 & command 2 echo "done"
Cependant, lorsque je veux arrêter le script bash et appuyer sur Ctrl + C , seule la deuxième command est arrêtée. La première command continue de fonctionner. Comment m'assurer que le script bash complet est arrêté? Ou dans tous les cas, comment puis-je arrêter les deux commands? Parce que dans ce cas, peu importe combien de fois j'appuie sur Ctrl + C la command continue à fonctionner et je suis obligé de fermer le terminal.
Si vous tapez
command 1 & command 2
c'est égal à
command 1 & command 2
c'est-à-dire que cela exécutera la première command en arrière-plan, puis exécutera la deuxième command au premier plan. Cela signifie surtout que votre echo "done"
est imprimé après la fin de la command 2
même si la command 1
est encore en cours.
Vous voulez probablement
command 1 & command 2 & wait echo "done"
Cela va exécuter les deux commands en arrière-plan et attendre que les deux soient terminées.
Si vous appuyez sur CTRL-C, cela enverra uniquement le signal SIGINT au process de premier plan, c'est-à-dire la command 2
dans votre version ou wait
dans ma version.
Je suggère de mettre un piège comme ceci:
#!/bin/bash trap killgroup SIGINT killgroup(){ echo killing... kill 0 } loop(){ echo $1 sleep $1 loop $1 } loop 1 & loop 2 & wait
Avec le piège, le signal SIGINT produit par CTRL-C est piégé et remplacé par la fonction killgroup
, qui tue tous ces process.
Lorsque vous placez une command en arrière-plan à partir d'un script, le PID n'est pas affiché à l'écran. La variable embeddede $!
stocke le PID du dernier process afin que vous puissiez capturer le PID de command1 en l'utilisant.
command1 & echo $!
ferait écho au PID de command1.
Bash fournit également le piège embedded dans lequel vous pouvez utiliser pour save une séquence de commands à exécuter lorsque des signaux particuliers sont reçus. Vous pouvez utiliser ceci pour attraper le SIGINT et tuer la command1 avant de quitter le script principal, par exemple
#!/bin/bash onINT() { echo "Killing command1 $command1PID too" kill -INT "$commad1PID" exit } trap "onINT" SIGINT command1 & command1PID="$!" comamnd2 echo Done
Maintenant, alors que la command 2 est en cours d'exécution, en appuyant sur Ctrl C , les commands command1 et command2 seront envoyées SIGINT.
Les versions plus récentes de GNU Parallel feront ce que vous voulez:
parallel ::: "command 1" "command 2" echo "done"
Ou si la command
rest la même:
parallel command ::: 1 2 echo done
Regardez la video d'intro pour une introduction rapide: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Parcourez le tutoriel (man parallel_tutorial). Vous commandz en ligne avec l'amour pour cela.
Ctrl + C envoie un signal SIGINT à votre process frontal, qui est command2
. command1
est exécuté en arrière-plan, donc pas concerné par le stream d'input.
Lorsque vous tapez command1 &
, bash devrait vous donner le process 'PID, quelque chose comme [1234]
. Pour tuer ce process, vous pouvez utiliser kill 1234
. Maintenant, si vous avez les PID des commands command1
et command2
(regardez ps -ef
), vous pouvez utiliser kill
pour les terminer:
kill pid1 pid2 pid3 ...
Un petit truc serait d'exécuter les deux commands en arrière-plan, avec:
command1 & command2 &
Bash vous donnera les deux PID, prêts à être tués. Une autre astuce serait de ramener command1
au premier plan une fois que vous avez tué command2
:
command1 & command2 # Hit Ctrl+C : command2 terminates. fg # Bring back command1 to foreground. # Hit Ctrl+C again, command1 terminates.
Plus d'informations disponibles ici: http://linuxg.net/how-to-manage-background-and-foreground-processes/