web-dev-qa-db-fra.com

Comment tuer un script exécuté dans un terminal, sans fermer le terminal (Ctrl + C ne fonctionne pas)?

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.

Appuyer sur Ctrl + C ne suffit parfois pas, 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é.

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

34
becko

Vous avez peu d'options. La première consiste à arrêter le script (CtrlZ), obtenez le PID du script et envoyez SIGKILL au groupe de processus.

Lorsqu'une commande est exécutée dans un shell, le processus qu'il démarre commence 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 commande kill , le responsable du processus est désigné ainsi:

kill -PID

PID est l'ID de processus du script.

Exemple:

Prenons un script test.sh qui lance certains processus. Disons que vous l'avez exécuté 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, procédez comme suit:

kill -INT -17802

-INT est utilisé pour envoyer SIGINT et cette commande équivaut donc à appuyer sur CtrlC sur 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, utilisez pgrep pour trouver le PID.

L’une des commandes lancées par le script peut intercepter SIGINT, ce qui explique probablement pourquoi CtrlC est inefficace. Cependant, SIGKILL ne peut pas être intercepté et il s’agit généralement d’une option de dernier recours . Vous voudrez peut-être essayer SIGTERM (-TERM) avant de tuer. Ni SIGKILL ni SIGTERM ne peuvent être configurés comme raccourci clavier comme SIGINT est.

Tout cela n'a plus sa raison d'être si votre script ne contient pas de ligne Shebang. De this SO answer :

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é après le script (ni un processus avec le nom du script dans la ligne de commande) et pgrep échouera.

Toujours utiliser une ligne Shebang.

36
muru

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
6
Harris

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