Bash Loop - Làm cách nào để dừng vòng lặp khi tôi nhấn Control-C bên trong một lệnh?


35

Tôi đang rsyncing một vài thư mục. Tôi có một bash terminal mở và đang thực hiện một cái gì đó như thế này:

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

Tuy nhiên nếu tôi muốn dừng toàn bộ mọi thứ, tôi nhấn Control-C. Điều đó dừng rsync, nhưng sau đó nó tiếp tục đi đến cái tiếp theo. Trong trường hợp này, tôi nhận ra những gì đã xảy ra và sau đó chỉ cần nhấn Control-C như một kẻ điên cho đến khi mọi thứ hoạt động trở lại.

Có cách nào đó để sửa lỗi này không. Tôi muốn nó vì vậy nếu tôi có một vòng lặp như vậy và nhấn Control-C, nó sẽ đưa tôi trở lại vỏ bash của tôi.


6
Câu trả lời của Dennis là đúng, nhưng nếu bạn không làm điều đó, bạn không cần phải 'nhấn nó như một kẻ điên', chỉ cần giữ nó và để bàn phím lặp lại xử lý nó :-)
Kyle Brandt

Tôi luôn luôn giữ Cntl-C, thường hoạt động tốt.
Scott Alan Miller

Câu trả lời:


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

Điều này cũng sẽ thoát khỏi vòng lặp nếu một lần chạy rsync riêng lẻ không thành công vì một số lý do.


4
Mẹo bổ sung: nếu bạn đang ở trong một vòng lặp lồng nhau và muốn chấm dứt hoàn toàn, hãy sử dụng break 2(hoặc thay thế "2" bằng số vòng lặp lồng nhau mà bạn muốn chấm dứt).
Dolan Antenucci

26

Để mở rộng câu trả lời của Dennis, mã của bạn có thể trông như sau:

trap "echo Exited!; exit;" SIGINT SIGTERM

Để biết ví dụ hoạt động (điều đó xảy ra liên quan đến rsync), hãy xem http://gist.github.com/279849 .


Cảm ơn, đây là một giải pháp chung có hiệu quả với tôi
wi1

25

Bạn có thể đặt bẫy cho Control-C.

trap <command> SIGINT

sẽ thực thi commandkhi nhấn Control-C. Chỉ cần đặt trapcâu lệnh ở đâu đó trong tập lệnh của bạn tại điểm mà bạn muốn nó trở nên hiệu quả.


6

Khi bạn đặt một chuỗi lệnh bên trong dấu ngoặc đơn, chuỗi sẽ hoạt động như một quy trình duy nhất và sẽ nhận được SIGINT và chấm dứt khi bạn nhấn Ctrl- C:

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

Nhưng! Trong trường hợp rsynclệnh, nó cho phép nhiều nguồn, do đó mã bạn đã viết sẽ được viết tốt hơn như sau:

rsync -a * example.com:somewhere/

6
  1. Nhấn Ctrl-Zđể tạm dừng kịch bản;
  2. kill %%

Tín dụng, giải thích và chi tiết hơn trong câu trả lời này .


Điều này thật tuyệt vì nó hoạt động "post facto" khi bạn muốn làm gián đoạn một vòng lặp dài mà bạn đã bắt đầu.
Nick Matteo

0

Tôi có xu hướng đặt một lệnh khác trong vòng lặp của tôi có thể dễ dàng bị gián đoạn. Nó đòi hỏi phải nhấn hai ctrl-C.

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

Đây không phải là một giải pháp tuyệt vời cho rsync này, mà bạn có thể muốn chạy nhanh. Nhưng nó hoạt động tốt cho các vòng lặp khác, như cái này:

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

Vòng lặp này sẽ tìm kiếm lại địa chỉ của example.com mỗi lần qua vòng lặp, rất hữu ích nếu bạn đang xem thay đổi DNS.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.