Bẫy 'Ctrl + c' cho tập lệnh bash nhưng không cho quá trình mở trong tập lệnh này


11

Tôi đã cố gắng để có một chương trình tương tác trong một kịch bản bash:

my_program

Và tôi ước có thể đóng nó bằng 'Ctrl + c'. Nhưng khi tôi làm điều đó kịch bản của tôi cũng đóng cửa.

Tôi biết về.

trap '' 2
my_program
trap 2

Nhưng trong trường hợp này, tôi không thể đóng my_programbằng Ctrl + c.

Bạn có biết làm thế nào để cho phép Ctrl + c trên một chương trình, nhưng không đóng tập lệnh chạy nó không?

EDIT: thêm ví dụ

#!/bin/bash
my_program
my_program2

Nếu tôi sử dụng Ctrl + c để đóng my_program, my_program2sẽ không bao giờ được thực thi vì toàn bộ tập lệnh đã thoát.

Câu trả lời:


13

Bạn nên sử dụng trap true 2hoặc trap : 2thay vì trap '' 2. Đó là những gì "bẫy giúp đỡ" trong vỏ bash nói về nó:

Nếu ARG là chuỗi null, mỗi SIGNALClickEC bị bỏ qua bởi shell và bởi các lệnh mà nó gọi .

Thí dụ:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done

2
Làm thế nào về việc giết tails thay vì giết mèo lần sau?
kubanchot

12

Bạn có thể đặt lại một cái bẫy về mặc định của nó bằng cách đưa ra lệnh bẫy -làm đối số hành động của nó. Nếu bạn làm điều này trong một lớp con , nó sẽ không ảnh hưởng đến bẫy trong vỏ cha. Trong tập lệnh của bạn, bạn có thể thực hiện việc này cho từng lệnh mà bạn cần phải ngắt bằng Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.

1
Mặc dù câu trả lời được chấp nhận có lẽ tốt hơn và hợp quy hơn cho shell, nhưng đây là một câu trả lời tuyệt vời ở chỗ nó đưa ra nguyên tắc chung (không dành riêng cho vỏ) về cách thực hiện loại mặt nạ / bỏ qua tín hiệu này một cách an toàn.
R .. GitHub DỪNG GIÚP ICE

Tôi đoán bạn có thể exec my_programtrong subshell, để hiệu quả hơn một chút.
Toby Speight

@R .. điều đó hoàn toàn không phải là vỏ cụ thể - nếu bạn đặt tín hiệu thành SIG_IGN (đó là cái bẫy có chuỗi rỗng đang thực hiện), trạng thái đó sẽ được kế thừa thông qua exec (), ngoại trừ SIGCHLD. Đó là hành vi bắt buộc POSIX. Xem thêm câu trả lời cho stackoverflow.com/questions/32708086/ từ
mosvy

@mosvy: Tôi không thấy phần nào trong nhận xét của bạn mà bạn không đồng ý. Toàn bộ quan điểm của tôi là "mặt nạ / bỏ qua trước ngã ba, vạch mặt / bỏ dấu ở trẻ trước khi thực thi" là một nguyên tắc chung hữu ích để biết bên ngoài bối cảnh chỉ là lập trình shell.
R .. GitHub DỪNG GIÚP ICE

1
Đây là một câu trả lời rất hữu ích. Là một người dùng Linux có kinh nghiệm, tôi có thể nói rằng tôi chưa bao giờ nghe về điều này trước đây. Nó có khá nhiều công dụng ... bạn có upvote và bookmark của tôi.
Dev

-1


Khi bạn sử dụng Crtl+ C, bạn làm gián đoạn chương trình (" giết " nó).
Những gì bạn có thể đang tìm kiếm là tạm dừng chương trình của bạn (" tạm dừng " nó). Đối với điều này, bạn có thể sử dụng Crtl+ Z.
Khi chương trình của bạn bị tạm dừng, bạn có thể xem nó bằng cách sử dụng jobs. Ví dụ:
[1]+ Stopped ./foobar
Ở đây tôi chỉ có một công việc, công việc số 1, nhưng có thể có nhiều hơn một - mỗi công việc có một số riêng.
Bạn có thể kiểm soát quá trình bị đình chỉ bằng cách sử dụng một số lệnh, ví dụ bg, fgkill.
bg %1sẽ khởi động lại công việc # 1 trong b ack g tròn
fg %1sẽ khởi động lại công việc # 1 trong f quặngg round
kill %1sẽ giết công việc # 1
Lưu ý rằng bạn có thể sử dụng bgfgkhông có đối số nếu bạn chỉ có một công việc đang hoạt động.


Cảm ơn bạn nhưng không, tôi muốn làm Ctrl + c.
bob dylan
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.