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.