Bash Loop - Come fermare il loop quando premo Control-C all'interno di un comando?


35

Sto sincronizzando alcune directory. Ho un terminale bash aperto e sto eseguendo qualcosa del genere:

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

Tuttavia, se voglio fermare tutto, premo Control-C. Ciò interrompe il rsync, ma poi continua con quello successivo. In questo caso mi rendo conto di quello che è successo e poi premo Control-C come un pazzo fino a quando le cose non funzionano di nuovo.

C'è un modo per 'risolvere' questo. Lo voglio quindi se ho un loop del genere, e premo Control-C, che mi riporterà alla mia shell bash.


6
La risposta di Dennis è quella giusta, ma se non l'hai fatto, non devi "premerlo come un pazzo", basta tenerlo premuto e lasciare che la tastiera lo ripeti gestirlo :-)
— Kyle Brandt

Tengo sempre premuto Cntl-C, generalmente funziona bene.
— Scott Alan Miller,

Risposte:


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

Questo uscirà anche dal ciclo se una singola esecuzione rsync fallisce per qualche motivo.


4
Suggerimento aggiuntivo: se si è in un ciclo nidificato e si desidera terminare completamente, utilizzare break 2(o sostituire "2" con il numero di cicli nidificati che si desidera terminare).
— Dolan Antenucci il

26

Per espandere la risposta di Dennis, il tuo codice potrebbe apparire come:

trap "echo Exited!; exit;" SIGINT SIGTERM

Per un esempio funzionante (che coinvolge rsync), controlla http://gist.github.com/279849 .


Grazie, questa è una soluzione generica che ha funzionato per me
— wi1

25

È possibile impostare una trap per Control-C.

trap <command> SIGINT

eseguirà il commandquando si preme Control-C. trapMetti la frase da qualche parte nella tua sceneggiatura nel punto in cui vuoi che diventi efficace.



6

Quando inserisci una stringa di comandi tra parentesi, la stringa agirà come un singolo processo e riceverà il SIGINT e terminerà quando premi Ctrl- C:

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

Ma! Nel caso del rsynccomando, consente più origini, quindi il codice che hai scritto sarebbe meglio scritto come:

rsync -a * example.com:somewhere/

0

Tendo a inserire un altro comando nel mio ciclo che può essere facilmente interrotto. Richiede due ctrl-C per essere premuto.

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

Non è una soluzione così grande per questo rsync, che probabilmente vorrai eseguire rapidamente. Ma funziona bene per altri loop, come questo:

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

Questo loop ricercherà l'indirizzo di example.com ogni volta attraverso il loop, il che è utile se stai cercando una modifica DNS.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.