Làm cách nào để tắt tập lệnh đang chạy trong thiết bị đầu cuối mà không đóng thiết bị đầu cuối (Ctrl + C không hoạt động)?


35

Tôi đã viết một tập lệnh bash gọi một số chương trình khác và thực thi một loạt các lệnh. Tôi chạy tập lệnh này từ thiết bị đầu cuối. Bây giờ tôi muốn giết kịch bản.

Nhấn Ctrl + Cđôi khi không cắt được, tôi nghĩ bởi vì đôi khi tập lệnh đang thực thi một chương trình khác và vì một lý do nào đó, tín hiệu tiêu diệt không hoạt động.

Tuy nhiên, nếu tôi đóng cửa sổ terminal, nó sẽ giết tập lệnh.

Có điều gì tôi có thể làm (kết hợp bàn phím), tương tự như đóng cửa sổ đầu cuối, mà không thực sự đóng cửa sổ đầu cuối (tôi không muốn mất lịch sử lệnh, thư mục hiện tại, lịch sử đầu ra, v.v.)?


8
Trong những trường hợp như vậy tôi cố gắngCtrl + z
kenn

Và sau khi Ctrl + zchạy:kill -9 $(pgrep -f your_script.sh)
Noam Manos

Câu trả lời:


38

Bạn có vài lựa chọn. Một là dừng tập lệnh ( CtrlZ), lấy PID của tập lệnh và gửi SIGKILLcho nhóm quy trình.

Khi một lệnh được thực thi trong shell, quá trình nó bắt đầu và tất cả các phần tử con của nó là một phần của cùng một nhóm quy trình (trong trường hợp này là nhóm quy trình tiền cảnh). Để gửi tín hiệu cho tất cả các quy trình trong nhóm này, bạn gửi nó cho người lãnh đạo quy trình. Đối với killlệnh, người lãnh đạo quá trình được ký hiệu như vậy:

kill -PID

Trong trường hợp PIDlà quá trình ID của kịch bản.

Thí dụ:

Hãy xem xét một kịch bản test.shkhởi chạy một số quy trình. Giả sử bạn chạy nó trong một cái vỏ:

$ ./test.sh

Trong một nhà ga khác,

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

Trong trường hợp này, để gửi tín hiệu đến nhóm quy trình được tạo bởi test.sh, bạn sẽ làm:

kill -INT -17802

-INTđược sử dụng để gửi SIGINT, và vì vậy lệnh này tương đương với việc nhấn CtrlCvào thiết bị đầu cuối. Gửi SIGKILL:

kill -KILL -17802

Bạn chỉ cần dừng tập lệnh nếu bạn không thể mở một thiết bị đầu cuối khác. Nếu bạn có thể, sử dụng pgrepđể tìm ra PID.

Một trong những lệnh mà tập lệnh khởi chạy có thể bị kẹt SIGINT, đó có thể là lý do tại sao CtrlCkhông hiệu quả. Tuy nhiên, SIGKILLkhông thể bị mắc kẹt và nó thường là lựa chọn cuối cùng . Bạn có thể muốn thử SIGTERM( -TERM) trước khi giết. Không SIGKILLhoặc SIGTERMcó thể được thiết lập như một bàn phím tắt đường SIGINTlà.

Tất cả điều này là moot nếu tập lệnh của bạn không chứa một dòng shebang. Từ câu trả lời SO này :

Thông thường, shell cha đoán rằng tập lệnh được viết cho cùng một trình bao (các shell giống như Bourne tối thiểu chạy tập lệnh với / bin / sh, bash chạy nó dưới dạng một quy trình con bash) ...

Vì điều này, khi tập lệnh được thực thi, bạn sẽ không tìm thấy một quy trình được đặt tên theo tập lệnh (hoặc một quy trình có tên của tập lệnh trong dòng lệnh) và pgrepsẽ thất bại.

Luôn luôn sử dụng một dòng shebang.


Có một sự kết hợp bàn phím cho SIGKILLhay SIGTERM?
vẫy gọi

@becko Không, và bạn không thể thiết lập một: superuser.com/a/417991/334516
muru

pgrep test.shkhông trả lại PID cho tôi. Tôi đã thử một thử nghiệm đơn giản.sh: for i in {1..30}; do sleep 1 echo $i done Trong khi test.shđang chạy, tôi thực thi pgrep test.shtrong một thiết bị đầu cuối khác, nhưng không có gì được trả về. Chuyện gì vậy?
vẫy gọi

1
@becko bạn đã chạy script như thế nào? Cũng thử pgrep -f test.sh.
muru

pgrep -f test.shcũng không hoạt động. Tôi chạy tập lệnh với./test.sh
becko

6

Nếu bạn biết các quy trình được liên kết với tập lệnh, bạn có thể tìm thấy PID của chúng bằng cách sử dụng

 ps -A

và sau đó sử dụng số PID để tiêu diệt các quá trình tương ứng bằng cách sử dụng

 kill -9 PID_Number

1
Điều đó quá phức tạp. Kịch bản sinh ra một số chương trình khác và các chương trình này cũng sinh ra các quá trình song song. Rất khó để theo dõi tất cả các quá trình này. Phải có một giải pháp đơn giản hơn, một cái gì đó tương tự với những gì xảy ra khi bạn đóng cửa sổ terminal.
vẫy gọi

Bạn có thể thử pkill -P $$
Harris

1

Như Harris nói bạn có thể chạy Kill -9 PID_Numbernhưng bạn cũng có thể cài đặt gói được biết là htopcó trình duyệt quy trình tương tác giúp việc tìm kiếm các quy trình cụ thể dễ dàng hơn rất nhiều. htop cũng hỗ trợ quá trình tiêu diệt.

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.