Làm cách nào để tạo ctrl + c / not / làm gián đoạn vòng lặp while?


11

Cho vòng lặp này:

while sleep 10s ; do
  something-that-runs-forever
done

Khi tôi nhấn Ctrl + C, toàn bộ vòng lặp while bị gián đoạn. Những gì tôi muốn làm là làm gián đoạn quá trình "một cái gì đó", để 10 giây trôi qua, và sau đó khởi động lại "một cái gì đó".

Làm cách nào để tạo ctrl + c chỉ ảnh hưởng đến "cái gì đó" chứ không ảnh hưởng đến vòng lặp while?

EDIT: "ngắt" như trong SIGINT. Giết chết. Huỷ bỏ. Chấm dứt. Không "ngắt" như trong "tạm dừng".


Nếu bạn chỉ muốn tạm dừng nó, tại sao không sử dụng Ctrl + Z, đợi 10 giây và chạy fg? Tại sao lại sử dụng Ctrl + C?
terdon

@terdon: Cảm ơn vì nhận xét, có thể tôi đã vội vàng trả lời. Cần đọc thêm về yêu cầu của OP
Inian

@terdon: Tôi không muốn tạm dừng nó. Tôi muốn 10 giây trôi qua, như tôi đã viết.
bos

Bạn nói : What I want to do is to interrupt the "something"-process, let 10 seconds pass, and then restart "something". Nếu bạn nhấn Ctrl + Z, đợi 10 giây rồi chạy fg, đó chính xác là điều sẽ xảy ra. Có lẽ bạn có thể chỉnh sửa câu hỏi của mình và đưa ra một ví dụ cụ thể để chúng ta có thể hiểu rõ hơn?
terdon

3
Tôi nghĩ rằng trong bối cảnh ngắt Ctrl + C là không rõ ràng, nhưng rõ ràng tôi đã sai. Bây giờ tôi đã chỉnh sửa.
bos

Câu trả lời:


18

Nó sẽ hoạt động nếu bạn chỉ cần trap SIGINTmột cái gì đó. Thích :( true).

#!/bin/sh
trap ":" INT    
while sleep 10s ; do
    something-that-runs-forever
done

Làm gián đoạn something...không làm cho thoát khỏi vỏ bây giờ, vì nó bỏ qua tín hiệu. Tuy nhiên, nếu bạn ^ C sleepquá trình, nó sẽ thoát với một lỗi và vòng lặp dừng do đó. Di chuyển sleepvào bên trong của vòng lặp hoặc thêm một cái gì đó như || trueđể ngăn chặn điều đó.

Lưu ý rằng nếu bạn sử dụng trap "" INTđể bỏ qua hoàn toàn tín hiệu (thay vì gán lệnh cho nó), thì nó cũng bị bỏ qua trong quy trình con, do đó bạn cũng không thể làm gián đoạn something.... Điều này được đề cập rõ ràng trong ít nhất là hướng dẫn của Bash :

Nếu arg là chuỗi null, thì tín hiệu được chỉ định bởi mỗi sigspec sẽ bị bỏ qua bởi shell và ra lệnh nó gọi. [...] Tín hiệu bị bỏ qua khi vào vỏ không thể bị giữ lại hoặc đặt lại.


Điều này có thể đạt được trong vỏ hiện tại là tốt? (Không có trong tập lệnh.)

1
Bạn có thể muốn do (trap - INT; something-that-runs-forever)cho phép ngắt lệnh. Ngoài ra, bạn không cần phải chạy :- bạn chỉ có thể sử dụng một chuỗi trống để bỏ qua tín hiệu : trap '' INT. Tất cả điều này là POSIX và sẽ hoạt động trên mọi shell tuân thủ (không chỉ Bash).
Toby Speight

Cũng lưu ý rằng viết SIGINTđầy đủ không hoàn toàn di động: " Việc triển khai có thể cho phép các tên có SIGtiền tố hoặc bỏ qua trường hợp trong tên tín hiệu như một phần mở rộng . " (Nhấn mạnh của tôi)
Toby Speight

bạn có thể chuyển chuỗi trống dưới dạng hành động để bỏ qua tín hiệu, ví dụ: trap "" INT(cũng là posix)
daf

@TobySpeight, lý do tôi sử dụng trap :thay vì trap ""chính xác là để không bỏ qua tín hiệu (nhưng thay vào đó là tín hiệu không thay thế), do đó chúng tôi không cần phải làm gì khác để có thể làm gián đoạn somethingchương trình chính .
ilkkachu

0

Một tùy chọn khác là something-that-runs-foreverxử lý tín hiệu (thoát một cách duyên dáng khi nhận được). Tất nhiên, nó chỉ có ý nghĩa khi chương trình này được sử dụng trong nhiều tập lệnh và hành vi mong muốn trên CTRL+ Clà giống nhau một cách có hệ thống - để tiếp tục thực thi tập lệnh.


ITYM "ngủ và tự thực hiện lại", không "thoát ra một cách duyên dáng"?
Toby Speight
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.