Come uccidere uno script in esecuzione nel terminale, senza chiudere il terminale (Ctrl + C non funziona)?


36

Ho scritto uno script bash che chiama molti altri programmi ed esegue un sacco di comandi. Eseguo questo script dal terminale. Ora voglio uccidere la sceneggiatura.

Premere a Ctrl + Cvolte non lo taglia, penso perché a volte lo script sta eseguendo un altro programma e per qualche ragione il segnale di kill non funziona.

Tuttavia, se chiudo la finestra del terminale, questo uccide lo script.

C'è qualcosa che posso fare (una combinazione di tastiera), che è analogo alla chiusura della finestra del terminale, senza effettivamente chiudere la finestra del terminale (non voglio perdere la cronologia dei comandi, la directory corrente, la cronologia di output, ecc.)?


8
In questi casi ci provoCtrl + z
kenn

E dopo l' Ctrl + zesecuzione:kill -9 $(pgrep -f your_script.sh)
Noam Manos,

Risposte:


38

Hai poche opzioni. Uno è quello di interrompere lo script ( CtrlZ), ottenere il PID dello script e inviarlo SIGKILLal gruppo di processi.

Quando un comando viene eseguito in una shell, il processo inizia e tutti i suoi figli fanno parte dello stesso gruppo di processi (in questo caso, il gruppo di processi in primo piano). Per inviare un segnale a tutti i processi in questo gruppo, lo si invia al leader del processo. Per il killcomando, il leader del processo è indicato in questo modo:

kill -PID

Dov'è PIDl'ID del processo dello script.

Esempio:

Considera uno script test.shche avvia alcuni processi. Supponi di averlo eseguito in una shell:

$ ./test.sh

In un altro terminale,

$ 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)

In questo caso, per inviare un segnale al gruppo di processo creato da test.sh, è necessario:

kill -INT -17802

-INTviene utilizzato per inviare SIGINT, quindi questo comando equivale a premere CtrlCsul terminale. Per inviare SIGKILL:

kill -KILL -17802

Devi solo interrompere lo script se non riesci ad aprire un altro terminale. Se puoi, usa pgrepper trovare il PID.

Uno dei comandi lanciati dallo script potrebbe essere in trappola SIGINT, motivo per cui è probabilmente CtrlCinefficace. Tuttavia, SIGKILLnon può essere intrappolato ed è di solito un'opzione di ultima istanza . Potresti voler provare SIGTERM( -TERM) prima di andare per l'uccisione. Né SIGKILLoppure SIGTERMpuò essere impostato come un scorciatoia da tastiera il modo SIGINTè.

Tutto questo è discutibile se la tua sceneggiatura non contiene una riga shebang. Da questa risposta SO :

Di solito la shell genitore indovina che lo script è scritto per la stessa shell (le shell minimali tipo Bourne eseguono lo script con / bin / sh, bash lo esegue come sottoprocesso bash) ...

Per questo motivo, quando lo script viene eseguito, non troverai un processo che prende il nome dallo script (o un processo con il nome dello script nella riga di comando) e pgrepfallirà.

Usa sempre una linea shebang.


Esiste una combinazione di tasti per SIGKILLo SIGTERM?
becko,

@becko No, e non puoi crearne uno: superuser.com/a/417991/334516
muru

pgrep test.shnon restituisce il PID per me. Ho provato un semplice test.sh: for i in {1..30}; do sleep 1 echo $i done mentre test.shè in esecuzione, eseguo pgrep test.shin un altro terminale, ma non viene restituito nulla. Cosa c'è che non va?
becko,

1
@becko come hai eseguito lo script? Prova anche pgrep -f test.sh.
muru,

pgrep -f test.shnon funziona neanche. ./test.sh
Eseguo

6

Se conosci i processi associati allo script, puoi trovare il loro PID usando

 ps -A

e quindi usa il numero PID per terminare i processi corrispondenti usando

 kill -9 PID_Number

1
È troppo complicato. Lo script genera molti altri programmi e questi programmi generano anche processi paralleli. È molto difficile tenere traccia di tutti questi processi. Ci deve essere una soluzione più semplice, qualcosa di analogo a ciò che accade quando si chiude la finestra del terminale.
becko,

Puoi provare pkill -P $$
Harris

1

Come ha detto Harris, potresti eseguire Kill -9 PID_Numberma anche installare il pacchetto noto htopper avere un browser di processo interattivo che semplifica la ricerca di processi specifici. htop supporta anche i processi di uccisione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.