Bash Loop - Como interromper o loop quando pressiono Control-C dentro de um comando?

35

Estou sincronizando alguns diretórios. Eu tenho um terminal bash aberto e estou executando algo como isto:

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

No entanto, se eu quiser parar as coisas inteiras, pressiono Control-C. Isso interrompe o rsync, mas continua para o próximo. Nesse caso, percebo o que aconteceu e, em seguida, pressione Control-C como um louco até que as coisas funcionem novamente.

Existe alguma maneira de 'consertar' isso. Quero que, se eu tiver um loop como esse e pressione Control-C, ele retorne ao meu shell bash.

Rory
fonte
6
A resposta de Dennis é a certa, mas se você não fez isso, não precisa 'pressionar como um louco', apenas segure-a e deixe o teclado repetir :-)
Kyle Brandt
Eu sempre pressiono Cntl-C, geralmente funciona bem.
Scott Alan Miller

Respostas:

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

Isso também sairá do loop se uma execução rsync individual falhar por algum motivo.

Kenster
fonte
4
Dica adicional: se você estiver em um loop aninhado e quiser finalizar completamente, use break 2(ou substitua "2" pelo número de loops aninhados que deseja finalizar).
precisa saber é o seguinte
26

Para expandir a resposta de Dennis, seu código pode se parecer com:

trap "echo Exited!; exit;" SIGINT SIGTERM

Para um exemplo de trabalho (que envolve o rsync), consulte http://gist.github.com/279849 .

Ian Greenleaf Young
fonte
Obrigado, esta é uma solução genérica que funcionou para mim
ICG1
25

Você pode definir uma interceptação para Control-C.

trap <command> SIGINT

executará commandquando Control-C for pressionado. Basta colocar a trapdeclaração em algum lugar do seu script, no ponto em que você deseja que ela se torne eficaz.

Pausado até novo aviso.
fonte
6

Quando você coloca uma série de comandos dentro de parênteses, a corda vai agir como um processo único, e receberá o SIGINT e terminar quando você bate Ctrl- C:

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

Mas! No caso do rsynccomando, ele permite várias fontes, portanto o código que você escreveu seria melhor escrito como:

rsync -a * example.com:somewhere/
anfetamaquina
fonte
6
  1. Pressione Ctrl-Zpara suspender o script;
  2. kill %%

Créditos, explicações e mais detalhes nesta resposta .

Skippy le Grand Gourou
fonte
Isso é ótimo porque funciona "post facto" quando você deseja interromper um loop de longa execução que você já iniciou.
Nick Matteo
0

Costumo colocar outro comando no meu loop que pode ser facilmente interrompido. Requer que dois ctrl-Cs sejam pressionados.

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

Não é uma solução ótima para este rsync, que você provavelmente deseja executar rapidamente. Mas funciona bem para outros loops, como este:

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

Esse loop pesquisará novamente o endereço de example.com todas as vezes, o que é útil se você estiver procurando por uma alteração no DNS.

Alan Porter
fonte