Tengo un comando que quiero que se ejecute de nuevo automáticamente cada vez que termine, así que ejecuté algo como esto:
while [ 1 ]; do COMMAND; done;
pero si no puedo detener el bucle con Ctrl-c , eso acaba con COMMAND
y no el ciclo completo.
¿Cómo podría lograr algo similar pero que pueda detener sin tener que cerrar la terminal?
Comentarios
- Si ‘ m en bash, simplemente uso Ctrl-Z para detener el trabajo y luego » matar% 1 » para matarlo.
- Solo espera … Linus fue citado diciendo: “Todos sabemos que Linux es genial … hace bucles infinitos en 5 segundos «. – así que realmente … solo espera unos segundos más, debería completarse.
- ¡@PaulCager también funcionó para mí! ¿Por qué funciona donde Ctrl-C lo hace? no?
- @cirosantilli mata el trabajo externo (el bash » envoltorio «). En algunas situaciones, ganó ‘ t eliminar inmediatamente el » COMMAND «, por ejemplo , si lo pone en segundo plano, puede escabullirse vivo incluso si ‘ s padre está muerto. Pero el ciclo está muerto, y esa ‘ es la parte importante.
Respuesta
Verifique el estado de salida del comando. Si el comando terminó con una señal, el código de salida será 128 + el número de la señal. De la documentación en línea de GNU para bash :
Para los propósitos del shell, un comando que sale con un estado de salida cero ha tenido éxito. Un estado de salida distinto de cero indica falla. Este esquema aparentemente contrario a la intuición se utiliza para que haya una forma bien definida de indicar el éxito y una variedad de formas de indicar varios modos de falla. Cuando un comando termina en una señal fatal cuyo número es N, Bash usa el valor 128 + N como estado de salida.
POSIX también especifica que el valor de un comando que termina con una señal es mayor que 128, pero no parece especificar su valor exacto como lo hace GNU:
El estado de salida de un comando que terminó porque recibió una señal se informará como mayor que 128.
Por ejemplo, si interrumpe un comando con control-C, el código de salida será 130, porque SIGINT es la señal 2 en los sistemas Unix. Entonces:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Comentarios
Respuesta
Puede detener y poner su trabajo en segundo plano mientras se ejecuta usando ctrl + z . Luego puede acabar con su trabajo con:
$ kill %1
Donde [1] es su número de trabajo.
Comentarios
- Consulte también esta respuesta para obtener explicaciones y más.
- Esta respuesta relativamente reciente simplemente funciona. Necesita ser Upvoted. +1
- Me ayudaste mucho. Esto es lo que he buscado en esta pregunta 🙂
Responder
Yo diría que sería mejor poner su bucle infinito en un script y manejar las señales allí. Aquí «un punto de partida básico . Estoy seguro de que querrá modificarlo para adaptarlo. La secuencia de comandos usa trap
para capturar ctrl – c (o SIGTERM
), elimina el comando («he usado sleep
aquí como prueba) y sale.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Comentarios
- Genial. Aquí ‘ s cómo utilicé este consejo para hacer un contenedor netcat de inicio automático:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- si agrega este
trap
enfoque al mismo script (bash) con el bucle infinito que se eliminará, use$$
en lugar de$!
(consulte aquí )
Responder
Por lo general, mantengo presionada la tecla Ctrl-C . Tarde o temprano «se registrará entre COMMAND
» sy así terminar el bucle while
. Tal vez haya una mejor manera.
Comentarios
- No estoy seguro de por qué, pero falla para ciertos COMANDOS como
paplay
en un archivo 1s . - Me funcionó
- Que ‘ es la fuerza bruta de todas las soluciones aquí. : /
Responder
Si ejecuta bash con -e
saldrá en cualquier condición de error:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Comentarios
- La primera línea aquí es de lejos la solución más simple para una secuencia de comandos trivial en la que ‘ no desea dedicar demasiado tiempo.
Respuesta
Por qué no simplemente,
while [ 1 ]; do COMMAND || break; done;
O cuando se usa en un script,
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Comentarios
- Solución muy elegante. ¿Pero no ‘ esto solo funcionaría si COMMAND siempre devuelve un estado de salida exitoso?
- Sí @howardh, eso ‘ s correcto.
Respuesta
- Siempre puede matar un proceso usando su PID, ahí » s no es necesario cerrar tu terminal
- Si quieres ejecutar algo en un bucle infinito como un demonio, entonces es mejor que lo pongas en segundo plano
-
while :
creará un bucle infinito y te ahorrará escribir el[ 1 ]
while :; do COMMAND; done &
Esto imprimirá el PID. Si sale del mensaje con ctrl+d
, el trabajo en segundo plano no se cerrará, y luego podrá finalizar el trabajo desde cualquier lugar usando kill PID
Si pierde la pista de su PID, puede usar pstree -pa $USER
o pgrep -fl ".*PROCESS.*"
para encontrarlo
Respuesta
Prefiero otra solución:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
En orden para cerrar el ciclo, simplemente haga:
rm .runcmd && kill `pidof COMMAND`
Responder
Lo que funciona razonablemente bueno para mí es:
while sleep 1; do COMMAND; done
Esto funciona porque el sueño 1 se queda por un while y si obtiene ctrl + c, regresa con un valor distinto de cero y el ciclo terminará.
Comentarios
- +1, el tiempo de suspensión también puede ser reducido a
0.5
o0.1
:while sleep 0.1; do COMMAND; done
Respuesta
Utilice trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done
paplay alert.ogg
, tal vez porquepaplay
maneja la señal?