Thực thi lệnh hoặc hàm khi SIGINT hoặc SIGTERM được gửi đến chính tập lệnh cha, chứ không phải các tiến trình con


11

Hãy nói tôi có cái này script.sh

#!/bin/bash
exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

echo "Some other text"
#other commands here
sleep infinity

Tôi muốn script.shthực thi chức năng exit_scriptbất cứ khi nào nó nhận được SIGINThoặc SIGTERM Ví dụ:

killall script.sh # it will send SIGTERM to my script

và tôi muốn kịch bản của mình thực thi điều này

exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

Tôi đã cố gắng thực hiện tính năng này bằng cách sử dụng trap

trap exit_script SIGINT SIGTERM

Người trả lời câu hỏi của tôi đã chứng minh tôi sai.
nhưng nó không hoạt động vì trapdường như chỉ phản ứng với các tín hiệu được gửi đến các quá trình con / phụ. Khi mới bắt đầu, tôi không thể giải mã traptrang người đàn ông nên có lẽ tôi đã bỏ lỡ giải pháp.

Tôi đoán đó là những gì các chương trình "thực" như Chromium làm khi bạn gửi chúng SIGTERM

Từ https://major.io/2010/03/18/sigterm-vs-sigkill/

Ứng dụng có thể xác định những gì nó muốn làm sau khi nhận được SIGTERM. Trong khi hầu hết các ứng dụng sẽ dọn sạch tài nguyên của họ và dừng lại, một số có thể không.


2
nói chung, thề được coi là không phù hợp cho bài diễn văn tôn trọng
con mèo

chỉnh sửa đề xuất được chấp thuận ok, ok xong, không có gì vui tôi nhận được
bosa djo

Không phải là không có niềm vui nào được cho phép, nó chỉ bị coi là xúc phạm
con mèo

1
@cat Tôi đã nghĩ về lập luận của bạn và bạn đã đúng, xin lỗi vì tomfoolery của tôi
bosa djo

Câu trả lời:


15

trapphản ứng với các tín hiệu quá trình gọi chính nó. Nhưng bạn phải gọi nó trước khi nhận được tín hiệu. Ý tôi là, lúc bắt đầu kịch bản của bạn.

Hơn nữa, nếu bạn muốn sử dụng kill -- -$$, nó cũng gửi tín hiệu đến tập lệnh của bạn, bạn cần xóa bẫy trước khi chạy kill hoặc bạn sẽ kết thúc bằng một vòng lặp kill && bẫy vô hạn .

Ví dụ:

#!/bin/bash
exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    trap - SIGINT SIGTERM # clear the trap
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

trap exit_script SIGINT SIGTERM

echo "Some other text"
#other commands here
sleep infinity

Như đã giải thích trong các bình luận, vấn đề là kịch bản nhận được tín hiệu nhưng đang chờ chương trình ngủ kết thúc trước khi xử lý tín hiệu nhận được. Vì vậy, bạn nên giết các tiến trình con (quá trình ngủ trong trường hợp này) để chạy hành động bẫy. Bạn có thể làm điều đó với một cái gì đó như sau:

kill -- -$(pgrep script.sh)

Hoặc như đã nêu trong các ý kiến:

killall -g script.sh

1
Có lẽ tôi đang thiếu một cái gì đó vì nó không hoạt động, đây là những gì tôi làm. script.sh &; killall script.sh nhưng nó không làm gì cả.
bosa djo

Tôi thực thi script.sh &; # sau đó tôi làm kinh doanh của tôi; killall script.sh và nó không giết script.sh
bosa djo

1
Vấn đề có lẽ là kịch bản nhận được tín hiệu nhưng đang chờ chương trình ngủ kết thúc trước khi xử lý nó. Cố gắng ./script.sh & sleep 1 && kill -- -$(pgrep script.sh)gửi tín hiệu tiêu diệt đến các tiến trình con của tập lệnh của bạn.
zuazo

@zuazo Bạn nên thêm thông tin thú vị và quan trọng này vào câu trả lời của mình :)
mèo

1
Đẹp, bosa djo. Tôi đã thêm giải pháp thay thế của bạn vào câu trả lời ;-)
zuazo
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.