Comment tuer un script en cours d'exécution dans un terminal, sans fermer le terminal (Ctrl + C ne fonctionne pas)?

36

J'ai écrit un script bash qui appelle plusieurs autres programmes et exécute un tas de commandes. Je lance ce script depuis le terminal. Maintenant, je veux tuer le script.

Pressage Ctrl + C parfois ne suffit pas, je pense, car parfois, le script exécute un autre programme et, pour une raison quelconque, le signal de suppression ne fonctionne pas.

Cependant, si je ferme la fenêtre du terminal, le script est tué.

Y a-t-il quelque chose que je peux faire (une combinaison de clavier), analogue à la fermeture de la fenêtre du terminal, sans fermer réellement la fenêtre du terminal (je ne veux pas perdre l'historique des commandes, le répertoire actuel, l'historique de sortie, etc.)?

becko
la source
8
Dans de tels cas, j'essaieCtrl + z
kenn
Et après la Ctrl + zcourse:kill -9 $(pgrep -f your_script.sh)
Noam Manos le

Réponses:

38

Vous avez peu d'options. L'une consiste à arrêter le script ( CtrlZ), à obtenir le PID du script et à l'envoyer SIGKILLau groupe de processus.

Lorsqu'une commande est exécutée dans un shell, le processus qu'il démarre et tous ses enfants font partie du même groupe de processus (dans ce cas, le groupe de processus de premier plan). Pour envoyer un signal à tous les processus de ce groupe, vous l'envoyez au responsable du processus. Pour la killcommande, le responsable de processus est noté:

kill -PID

Où se PIDtrouve l'ID de processus du script.

Exemple:

Prenons un script test.shqui lance certains processus. Disons que vous l'avez couru dans un shell:

$ ./test.sh

Dans un autre terminal,

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

Dans ce cas, pour envoyer un signal au groupe de processus créé par test.sh, vous devez:

kill -INT -17802

-INTest utilisé pour envoyer SIGINT, et cette commande équivaut donc à appuyer CtrlCsur le terminal. Pour envoyer SIGKILL:

kill -KILL -17802

Vous ne devez arrêter le script que si vous ne pouvez pas ouvrir un autre terminal. Si vous le pouvez, utilisezpgrep pour trouver le PID.

L'une des commandes lancées par le script peut être un interception SIGINT, ce qui explique probablement CtrlCson inefficacité. Cependant, SIGKILLvous ne pouvez pas être pris au piège et il s’agit généralement d’une solution de dernier recours . Vous voudrez peut-être essayer SIGTERM( -TERM) avant de vous lancer. Ni SIGKILLou SIGTERMpeut être configuré comme un raccourci clavier comme SIGINTest.

Tout cela n'a plus sa raison d'être si votre script ne contient pas de ligne shebang. De cette réponse SO :

Généralement, le shell parent suppose que le script est écrit pour le même shell (des shells de type Bourne ressemblent au script avec / bin / sh, bash l'exécute en tant que sous-processus bash) ...

De ce fait, lorsque le script est exécuté, vous ne trouverez pas de processus nommé d'après le script (ni un processus avec le nom du script dans la ligne de commande) et pgrepéchouera.

Toujours utiliser une ligne de shebang.

muru
la source
Existe-t-il une combinaison de clavier pour SIGKILLou SIGTERM?
becko
@becko Non, et vous ne pouvez pas en créer un: superuser.com/a/417991/334516
muru
pgrep test.shne retourne pas le PID pour moi. J'ai essayé un test simple.sh: for i in {1..30}; do sleep 1 echo $i done Pendant test.shson exécution, je l'exécute pgrep test.shdans un autre terminal, mais rien n'est renvoyé. Qu'est-ce qui ne va pas?
Becko le
1
@becko comment avez-vous exécuté le script? Essayez aussi pgrep -f test.sh.
Muru
pgrep -f test.shne fonctionne pas non plus. Je lance le script avec./test.sh
becko le
6

Si vous connaissez les processus associés au script, vous pouvez trouver leur PID en utilisant

 ps -A

puis utilisez le numéro PID pour tuer les processus correspondants à l'aide de

 kill -9 PID_Number
Harris
la source
1
C'est trop compliqué. Le script génère plusieurs autres programmes, qui génèrent également des processus parallèles. Il est très difficile de suivre tous ces processus. Il doit y avoir une solution plus simple, quelque chose d'analogue à ce qui se passe lorsque vous fermez la fenêtre du terminal.
Becko
Pouvez-vous essayer pkill -P $$
Harris
1

Comme Harris l'a dit, vous pouvez exécuter, Kill -9 PID_Numbermais vous pouvez également installer le package htopdoté d'un navigateur de processus interactif facilitant grandement la recherche de processus spécifiques. htop prend également en charge les processus de mise à mort.

Bulbasaur Sommeil Privé
la source