¿Cómo hacer que ctrl + c / no / interrumpa el ciclo while?

11

Dado este bucle:

while sleep 10s ; do
  something-that-runs-forever
done

Cuando presiono Ctrl + C, todo el ciclo while se interrumpe. Lo que quiero hacer es interrumpir el proceso "algo", dejar pasar 10 segundos y luego reiniciar "algo".

¿Cómo hago que ctrl + c solo afecte "algo" y no el ciclo while?

EDITAR: "interrumpir" como en SIGINT. Matar. Abortar. Terminar. No "interrumpir" como en "pausa".

bos
fuente
Si solo quieres pausarlo, ¿por qué no usar Ctrl + Z, esperar 10 segundos y ejecutar fg? ¿Por qué usar Ctrl + C?
terdon
@terdon: Gracias por el comentario, puede ser que me apresuré con la respuesta. Necesito leer más sobre el requisito de OP
Inian
@terdon: no quiero pausarlo. Quiero que pasen 10 segundos, como escribí.
bos
Usted dijo: What I want to do is to interrupt the "something"-process, let 10 seconds pass, and then restart "something". Si presiona Ctrl + Z, espere 10 segundos y luego ejecute fg, eso es exactamente lo que sucederá. ¿Quizás podría editar su pregunta y dar un ejemplo específico para que podamos entender mejor?
terdon
3
Pensé que en el contexto de Ctrl + C la interrupción no era ambigua, pero obviamente estaba equivocado. Ya he editado.
bos

Respuestas:

18

Debería funcionar si solo haces trap SIGINTalgo. Me gusta :( true).

#!/bin/sh
trap ":" INT    
while sleep 10s ; do
    something-that-runs-forever
done

Interrumpir something...no hace que el shell salga ahora, ya que ignora la señal. Sin embargo, si usted ^ C el sleepproceso, saldrá con una falla, y el ciclo se detiene debido a eso. Mueva el sleepal interior del bucle o agregue algo como || truepara evitar eso.

Tenga en cuenta que si trap "" INTignora la señal por completo (en lugar de asignarle un comando), también se ignora en el proceso secundario, por lo que tampoco puede interrumpirla something.... Esto se menciona explícitamente en al menos el manual de Bash :

Si arg es la cadena nula, la señal especificada por cada sigspec es ignorada por el shell y los comandos que invoca. [...] Las señales ignoradas al ingresar al shell no pueden ser atrapadas o restablecidas.

ilkkachu
fuente
¿Se puede lograr esto también en el shell actual? (No en un script.)
1
Es posible que desee do (trap - INT; something-that-runs-forever)permitir la interrupción del comando. Además, no es necesario que ejecute :- sólo se puede utilizar una cadena vacía para ignorar una señal: trap '' INT. Todo esto es POSIX, y debería funcionar en cualquier shell compatible (no solo Bash).
Toby Speight el
Tenga en cuenta también que la escritura SIGINTen su totalidad no es estrictamente portátil: " Las implementaciones pueden permitir nombres con el SIGprefijo o ignorar caso de nombres de señal como una extensión . (El subrayado es mío)"
Toby Speight
puede pasar la cadena vacía como la acción para ignorar una señal, por ejemplo trap "" INT(también posix)
daf
@TobySpeight, la razón que usé en trap :lugar de eso trap ""fue exactamente eso, para que no se ignore la señal (sino que se convierta en un no-op), de modo que no necesitemos hacer nada más para poder interrumpir el somethingprograma principal .
ilkkachu
0

Otra opción es hacer que something-that-runs-forevermaneje la señal (que sale con gracia cuando se recibe). Por supuesto, solo tiene sentido hacerlo cuando este programa se usa en muchos scripts, y el comportamiento deseado en CTRL+ Ces sistemáticamente el mismo: continuar la ejecución del script.

Dmitry Grigoryev
fuente
¿ITYM "duerme y se vuelve a ejecutar", no "sale con gracia"?
Toby Speight