Ctrl-C avec deux commands simultanées dans bash

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/