¿Cómo detener el script de loop bash en la terminal?


55

Por ejemplo,

#!/bin/bash
while :
do
    sl
done

¿Cómo terminar este script bash?


1
Da más detalles. ¿Quieres detenerlo de forma interactiva o programática?
manatwork

1
puede presionar ctrl-cpara enviar la SIGINTseñal (en la mayoría de los depósitos) o puede presionar para ctrl-zenviar la SIGTSTPseñal (en la mayoría de los depósitos). En el caso de que haya presionado, ctrl-zel proceso relacionado no se elimina sino que se detiene. Puede reanudarlo con fg(al menos en bash)
user1146332

No, no funciona!
Yinyanghu

44
El problema no es el guión, sino el slcomando que creo que es un comando molesto para aquellos que escriben mal ls, que muestra un tren que pasa lentamente. Hasta donde sé, atrapa la SIGINTseñal y debe ser asesinado SIGKILL.

1
Gracias. No empacado para mi distribución, es por eso que no lo sabía / lo encontré. (Creo que no presentaré una solicitud)
Manatwork

Respuestas:


64

El programa slignora a propósito SIGINT, que es lo que se envía cuando presiona Ctrl+C. Entonces, en primer lugar, deberá decir que slno ignore SIGINTagregando el -eargumento.

Si intenta esto, notará que puede detener a cada individuo sl, pero aún así se repiten. También debes decirle bashque salgas después SIGINT. Puede hacer esto poniendo un trap "exit" INTantes del bucle.

#!/bin/bash
trap "exit" INT
while :
do
    sl -e
done

55
No lo tengo instalado para verificarlo, pero también puedes matarlo con SIGQUIT desde Ctrl- \
derobert el

121
  1. presione Ctrl-Zpara suspender el guión
  2. kill %%

El %%le dice al bash incorporado killque desea enviar una señal (SIGTERM por defecto) al trabajo en segundo plano suspendido más recientemente en el shell actual, no a un id de proceso.

También puede especificar trabajos por número o por nombre. por ejemplo, cuando suspende un trabajo con ^ Z, bash le dirá cuál es su número de trabajo con algo así [n]+ Stopped, donde ndentro de los corchetes se encuentra el número de trabajo.

Para obtener más información sobre el control de trabajos y empleos en la matanza, ejecutar help jobs, help fg, help bg, y help killen bash, y la búsqueda de JOB CONTROL(todo en mayúsculas) o jobspecen la página de manual de bash.

p.ej

$ ./killme.sh 
./killme.sh: línea 4: sl: comando no encontrado
./killme.sh: línea 4: sl: comando no encontrado
./killme.sh: línea 4: sl: comando no encontrado
./killme.sh: línea 4: sl: comando no encontrado
./killme.sh: línea 4: sl: comando no encontrado
...
...
...
./killme.sh: línea 4: sl: comando no encontrado
^ Z
[1] + Detenido ./killme.sh
$ kill %%
PS 
[1] + Terminado ./killme.sh

En este ejemplo, el número del trabajo era 1, por kill %1lo que habría funcionado igual quekill %%

(NOTA: no lo he slinstalado, por lo que la salida es solo "comando no encontrado". En su caso, obtendrá lo que la salida sl produce. No es importante: ^Zsuspender y kill %%funcionará igual)


3
Otra buena respuesta!
Yinyanghu

2
Por cierto, para ejecutar rápidamente bucles como este, ^ Z puede ser una forma más confiable de matar el proceso que ^ C. ^ C se enviará al programa ( sl) que se ejecuta en el bucle, pero el script seguirá ejecutándose ... y comenzará otro sl. Si presiona ^ C varias veces muy rápido, puede matar tanto slel script como el script (si ninguno de ellos atrapa SIGINT). ^ Z suspenderá el script casi de inmediato (inmediatamente si no cuenta la salida almacenada en búfer que todavía se está imprimiendo en su terminal), por lo que puede eliminarlo conkill %%
cas

¡Exactamente! Tengo que decir " sles un programa divertido". ¡Esta vez, me vuelve a divertir! @ _ @
Yinyanghu

Solo responda que parece funcionar también cuando el ciclo no se llama desde un script sino directamente desde la línea de comandos.
Skippy le Grand Gourou

1
@DrewChapin No recuerdo cuándo / dónde me enteré, solo algo que he sabido "desde siempre". La página de manual de bash (búsqueda de jobspec ) dice:The symbols %% and %+ refer to the shell's notion of the current job, which is the last job stopped while it was in the foreground or started in the background. The previous job may be referenced using %-. If there is only a single job, %+ and %- can both be used to refer to that job
cas

7

Si desea que ctrl + c detenga el ciclo, pero no termine el script, puede colocarlo || breakdespués del comando que esté ejecutando. Mientras el programa que está ejecutando termine en ctrl + c, esto funciona muy bien.

#!/bin/bash
while :
do
    # ctrl+c terminates sl, but not the shell script
    sl -e || break
done

Si está en un bucle anidado, puede usar "break 2" para salir de dos niveles, etc.


1
más 1 para el descanso 2
flyingfinger

3

Puede terminar ese script presionando Ctrl + C desde la terminal donde comenzó este script. Por supuesto, este script debe ejecutarse en primer plano para que pueda detenerlo con Ctrl + C.

O puede encontrar el PID (ID de proceso) de ese script en otro terminal abierto:

ps -ef | grep <name_of_the_script>
kill -9 <pid_of_your_running_script>

Ambas formas deberían hacer el truco que estás pidiendo.


1
No se puede terminar con Ctrl + C desde la terminal. Así que tengo que matarlo por ps o top. ¡Solo quiero saber cómo matarlo directamente!
Yinyanghu

3

La forma más fácil es emitir la QUITseñal, que generalmente está conectada Control-Backslash.

Cuando veas el tren, presiona Control- \


1

Puede killel pidde shell (bash).
Acabo de intentarlo y funciona.
Porque no puedo ver el proceso desde ps -ef(el trabajo que ejecutamos en el script de bucle).


0

Otra forma de terminar todo el script sería poner en segundo plano el slcomando y luego atrapar la señal INTpara matar todo el grupo de proceso del script con la señal HUP.

#!/bin/bash

trap 'trap - INT; kill -s HUP -- -$$' INT
#trap 'trap - INT; kill -s HUP 0' INT

while :
do
   sl & wait
done


-1
while [ true ] 
do

  #check if script is running
  ps | grep script_name.sh | grep -v grep >/dev/null 2>&1

  if [ "$!" != "0" ] ; then
    break
  else

    kill -9 ` ps -ef | grep script_name.sh | cut -d "a" -f 1` 
    echo "kill -9 `get script PID`"

  fi

done

Esto debería ayudar.


2
¿Por qué crees que el PID del último comando de fondo será alguna vez 0?
manatwork

-1

Lo de matar es horrible, porque nunca ahora, si el script tiene que ejecutarse dos veces. Y tu código de salida está mal.

while [ something ]; do

 if [ somethingelse ]; then
   echo shut down script with exit code 0
   exit 0
 fi
done

echo something else not happend
exit 2 # Return val important for example for monitoring

No funciona Solución = usar perl. mientras abre propia fiesta

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.