Bash Loop: ¿cómo detener el ciclo cuando presiono Control-C dentro de un comando?

35

Estoy sincronizando algunos directorios. Tengo una terminal de bash abierta y estoy ejecutando algo como esto:

for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; done

Sin embargo, si quiero detener todo, presiono Control-C. Eso detiene el rsync, pero luego continúa con el siguiente. En este caso, me doy cuenta de lo que sucedió y luego presiono Control-C como un loco hasta que las cosas funcionen nuevamente.

¿Hay alguna manera de "arreglar" esto? Lo quiero, así que si tengo un bucle como ese, y presiono Control-C, me devolverá a mi shell bash.

Rory
fuente
66
La respuesta de Dennis es la correcta, pero si no lo hiciste, no tienes que 'presionarlo como un loco', solo sosténlo y deja que el teclado lo repita :-)
Kyle Brandt
Siempre mantengo presionado Cntl-C, generalmente funciona bien.
Scott Alan Miller

Respuestas:

33
for DIR in * ; do rsync -a $DIR example.com:somewhere/ || break; done

Esto también saldrá del ciclo si una ejecución individual de rsync falla por alguna razón.

Kenster
fuente
44
Sugerencia adicional: si está en un bucle anidado y desea terminar por completo, use break 2(o reemplace "2" con el número de bucles anidados que desea terminar).
Dolan Antenucci el
26

Para ampliar la respuesta de Dennis, su código podría verse así:

trap "echo Exited!; exit;" SIGINT SIGTERM

Para ver un ejemplo de trabajo (que involucra rsync), consulte http://gist.github.com/279849 .

Ian Greenleaf Young
fuente
Gracias, esta es una solución genérica que funcionó para mí
wi1
25

Puede establecer una trampa para Control-C.

trap <command> SIGINT

ejecutará commandcuando se presione Control-C. Simplemente coloque la trapdeclaración en algún lugar de su secuencia de comandos en un punto donde desee que se haga efectiva.

Pausado hasta nuevo aviso.
fuente
7
  1. Presione Ctrl-Zpara suspender el guión;
  2. kill %%

Créditos, explicaciones y más detalles en esta respuesta .

Skippy le Grand Gourou
fuente
Esto es genial porque funciona "post facto" cuando desea interrumpir un ciclo de larga duración que ya comenzó.
Nick Matteo
la mejor respuesta, gracias!
Kostanos hace
6

Cuando coloca una cadena de comandos entre paréntesis, la cadena actuará como un solo proceso, y recibirá el SIGINT y terminará cuando presione Ctrl- C:

(for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; done)

¡Pero! En el caso del rsynccomando, permite múltiples fuentes, por lo que el código que escribió se escribiría mejor como:

rsync -a * example.com:somewhere/
anfetamaquina
fuente
0

Tiendo a poner otro comando en mi bucle que se puede interrumpir fácilmente. Requiere presionar dos ctrl-C's.

for DIR in * ; do rsync -a $DIR example.com:somewhere/ ; sleep 1 ; done

No es una gran solución para este rsync, que probablemente quieras ejecutar rápidamente. Pero funciona bien para otros bucles, como este:

while true ; do ping -c 10 example.com ; sleep 1 ; done

Este bucle volverá a buscar la dirección de example.com cada vez a través del bucle, lo cual es útil si está buscando un cambio de DNS.

Alan Porter
fuente