¿Cómo matar un script que se ejecuta en la terminal, sin cerrar la terminal (Ctrl + C no funciona)?

36

He escrito un script bash que llama a varios otros programas y ejecuta un montón de comandos. Ejecuto este script desde la terminal. Ahora quiero matar el guión.

Presionar a Ctrl + Cveces no es suficiente, creo que porque a veces el script está ejecutando otro programa, y ​​por alguna razón la señal de apagado no funciona.

Sin embargo, si cierro la ventana de terminal, mata el script.

¿Hay algo que pueda hacer (una combinación de teclado), que sea análogo a cerrar la ventana de terminal, sin cerrar realmente la ventana de terminal (no quiero perder el historial de comandos, el directorio actual, el historial de salida, etc.)?

llamar
fuente
8
En tales casos lo intentoCtrl + z
kenn
Y después de Ctrl + zcorrer:kill -9 $(pgrep -f your_script.sh)
Noam Manos

Respuestas:

38

Tienes pocas opciones. Una es detener el script ( CtrlZ), obtener el PID del script y enviarlo SIGKILLal grupo de proceso.

Cuando un comando se ejecuta en un shell, el proceso se inicia y todos sus elementos secundarios forman parte del mismo grupo de procesos (en este caso, el grupo de procesos en primer plano). Para enviar una señal a todos los procesos en este grupo, debe enviarla al líder del proceso. Para el killcomando, el líder del proceso se denota así:

kill -PID

¿Dónde PIDestá el ID de proceso del script?

Ejemplo:

Considere una secuencia de comandos test.shque inicia algunos procesos. Digamos que lo ejecutó en un shell:

$ ./test.sh

En otra 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)

En este caso, para enviar una señal al grupo de procesos creado por test.sh, haría lo siguiente:

kill -INT -17802

-INTse usa para enviar SIGINT, por lo que este comando equivale a presionar CtrlCel terminal. Para enviar SIGKILL:

kill -KILL -17802

Solo necesita detener el script si no puede abrir otra terminal. Si puede, use pgreppara encontrar el PID.

Uno de los comandos que lanza el script puede ser atrapar SIGINT, por lo que probablemente no CtrlCsea ​​efectivo. Sin embargo, SIGKILLno puede quedar atrapado, y generalmente es una opción de último recurso . Es posible que desee probar SIGTERM( -TERM) antes de matar. Ninguno de los dos SIGKILL, o SIGTERMse puede configurar como un atajo de teclado el camino SIGINTes.

Todo esto es discutible si su script no contiene una línea shebang. De esta respuesta SO :

Por lo general, el shell principal adivina que el script está escrito para el mismo shell (un mínimo de shells tipo Bourne ejecuta el script con / bin / sh, bash lo ejecuta como un subproceso bash) ...

Debido a esto, cuando se ejecuta el script, no encontrará un proceso con el nombre del script (o un proceso con el nombre del script en la línea de comando) y pgrepfallará.

Siempre use una línea shebang.

muru
fuente
¿Hay una combinación de teclado para SIGKILLo SIGTERM?
Becko
@becko No, y no puedes configurar uno: superuser.com/a/417991/334516
muru
pgrep test.shno me devuelve el PID. Intenté un simple test.sh: for i in {1..30}; do sleep 1 echo $i done mientras se test.shestá ejecutando, ejecuto pgrep test.shen otro terminal, pero no se devuelve nada. Que pasa
Becko
1
@becko, ¿cómo ejecutaste el script? Intenta también pgrep -f test.sh.
muru
pgrep -f test.shtampoco funciona ./test.sh
Ejecuto
6

Si conoce los procesos que están asociados con el script, puede encontrar su PID usando

 ps -A

y luego use el número PID para matar los procesos correspondientes usando

 kill -9 PID_Number
Harris
fuente
1
Eso es muy complicado. El script genera varios otros programas, y estos programas también generan procesos paralelos. Es muy difícil hacer un seguimiento de todos estos procesos. Debe haber una solución más simple, algo análogo a lo que sucede cuando cierra la ventana del terminal.
Becko
¿Puedes probar pkill -P $$
Harris
1

Como dijo Harris, podría ejecutar, Kill -9 PID_Numberpero también podría instalar el paquete conocido htoppor tener un navegador de procesos interactivo que facilita mucho la búsqueda de procesos específicos. htop también admite procesos de eliminación.

Bulbasaur privado de sueño
fuente