Bash Loop - Jak zatrzymać pętlę po naciśnięciu Control-C wewnątrz polecenia?


35

Synchronizuję kilka katalogów. Mam otwarty terminal bash i wykonuję coś takiego:

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

Jeśli jednak chcę zatrzymać wszystko, naciskam Control-C. To zatrzymuje rsync, ale potem przechodzi do następnego. W tym przypadku zdaję sobie sprawę z tego, co się wydarzyło, a następnie po prostu naciskaj klawisz Control-C jak szaleniec, aż wszystko znów zadziała.

Czy jest jakiś sposób, aby to naprawić. Chcę tego, jeśli mam taką pętlę, i naciśnij Control-C, aby powrócił do mojej powłoki bash.


6
Odpowiedź Dennisa jest właściwa, ale jeśli tego nie zrobiłeś, nie musisz „naciskać jak szaleniec”, wystarczy przytrzymać i pozwolić klawiaturze powtórzyć :-)
Kyle Brandt

Zawsze przytrzymuję Cntl-C, ogólnie działa dobrze.
Scott Alan Miller

Odpowiedzi:


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

Spowoduje to również wyjście z pętli, jeśli z jakiegoś powodu pojedyncze uruchomienie rsync zakończy się niepowodzeniem.


4
Dodatkowa wskazówka: jeśli jesteś w zagnieżdżonej pętli i chcesz całkowicie zakończyć, użyj break 2(lub zamień „2” na liczbę zagnieżdżonych pętli, które chcesz zakończyć).
Dolan Antenucci

26

Aby rozwinąć odpowiedź Dennisa, kod może wyglądać następująco:

trap "echo Exited!; exit;" SIGINT SIGTERM

Dla działającego przykładu (który zdarza się obejmować rsync), sprawdź http://gist.github.com/279849 .


Dzięki, to jest ogólne rozwiązanie, które zadziałało dla mnie
wi1

25

Możesz ustawić pułapkę dla Control-C.

trap <command> SIGINT

wykona commandnaciśnięcie Control-C. Po prostu umieść trapinstrukcję gdzieś w skrypcie w miejscu, w którym chcesz, aby stała się skuteczna.


6

Kiedy umieścisz ciąg poleceń w nawiasach, ciąg będzie działał jako pojedynczy proces, otrzyma SIGINT i zakończy działanie po naciśnięciu Ctrl- C:

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

Ale! W przypadku rsyncpolecenia pozwala na wiele źródeł, więc kod, który napisałeś, byłby lepiej napisany jako:

rsync -a * example.com:somewhere/


0

Zwykle umieszczam w mojej pętli inne polecenie, które można łatwo przerwać. Wymaga naciśnięcia dwóch klawiszy Ctrl-C.

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

To nie jest takie świetne rozwiązanie dla tego rsync, który prawdopodobnie chcesz szybko uruchomić. Ale działa dobrze w przypadku innych pętli, takich jak ta:

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

Ta pętla będzie za każdym razem ponownie sprawdzać adres example.com, co jest przydatne, jeśli obserwujesz zmianę DNS.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.