Bash Loop - Bagaimana cara menghentikan loop ketika saya menekan Control-C di dalam perintah?

35

Saya sedang menyusun beberapa direktori. Saya memiliki terminal bash yang terbuka dan menjalankan sesuatu seperti ini:

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

Namun jika saya ingin menghentikan semuanya, saya tekan Control-C. Itu menghentikan rsync, tetapi kemudian melanjutkan ke yang berikutnya. Dalam hal ini saya menyadari apa yang telah terjadi dan kemudian tekan Control-C seperti orang gila sampai semuanya bekerja lagi.

Apakah ada cara untuk 'memperbaiki' ini. Saya menginginkannya jadi jika saya memiliki loop seperti itu, dan tekan Control-C, itu akan mengembalikan saya ke bash shell saya.

Rory
sumber
6
Jawaban Dennis adalah yang benar, tetapi jika Anda tidak melakukannya, Anda tidak perlu 'menekannya seperti orang gila', tahan saja dan biarkan keyboard mengulanginya :-)
Kyle Brandt
Saya selalu tahan Cntl-C, umumnya berfungsi dengan baik.
Scott Alan Miller

Jawaban:

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

Ini juga akan keluar dari loop jika menjalankan rsync individu gagal karena beberapa alasan.

Kenster
sumber
4
Kiat tambahan: jika Anda berada di loop bersarang, dan ingin mengakhiri sepenuhnya, gunakan break 2(atau ganti "2" dengan jumlah loop bersarang yang ingin Anda hentikan).
Dolan Antenucci
26

Untuk memperluas jawaban Dennis, kode Anda mungkin terlihat seperti:

trap "echo Exited!; exit;" SIGINT SIGTERM

Untuk contoh yang berfungsi (yang melibatkan rsync), lihat http://gist.github.com/279849 .

Ian Greenleaf Young
sumber
Terima kasih, ini adalah solusi umum yang bekerja untuk saya
wi1
25

Anda dapat mengatur jebakan untuk Control-C.

trap <command> SIGINT

akan mengeksekusi commandketika Control-C ditekan. Cukup letakkan trappernyataan di suatu tempat di naskah Anda pada titik di mana Anda ingin menjadi efektif.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
7
  1. Tekan Ctrl-Zuntuk menangguhkan skrip;
  2. kill %%

Kredit, penjelasan, dan detail lainnya dalam jawaban ini .

Skippy le Grand Gourou
sumber
Ini bagus karena ini berfungsi "post facto" ketika Anda ingin mengganggu loop lama yang sudah Anda mulai.
Nick Matteo
jawaban terbaik, terima kasih!
Kostanos
6

Saat Anda meletakkan string perintah di dalam tanda kurung, string akan bertindak sebagai satu proses, dan akan menerima SIGINT dan berakhir ketika Anda menekan Ctrl- C:

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

Tapi! Dalam kasus rsyncperintah, ini memungkinkan banyak sumber, sehingga kode yang Anda tulis akan lebih baik ditulis sebagai:

rsync -a * example.com:somewhere/
amphetamachine
sumber
0

Saya cenderung untuk menempatkan perintah lain di loop saya yang dapat dengan mudah terganggu. Ini membutuhkan dua ctrl-C untuk ditekan.

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

Ini bukan solusi yang bagus untuk rsync ini, yang mungkin ingin Anda jalankan dengan cepat. Tapi itu bekerja dengan baik untuk loop lain, seperti ini:

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

Loop ini akan mencari kembali alamat example.com setiap kali melalui loop, yang berguna jika Anda melihat perubahan DNS.

Alan Porter
sumber