Jalankan perintah atau fungsi ketika SIGINT atau SIGTERM dikirim ke skrip induk itu sendiri, bukan proses anak

11

Katakanlah saya punya ini 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

Saya ingin script.shmenjalankan fungsi exit_scriptsetiap kali menerima SIGINTatau SIGTERM Misalnya:

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

dan saya ingin skrip saya menjalankan ini

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

Saya mencoba menerapkan fitur ini menggunakan trap

trap exit_script SIGINT SIGTERM

Orang yang menjawab pertanyaan saya membuktikan saya salah.
tetapi tidak berhasil karena traptampaknya hanya bereaksi terhadap sinyal yang dikirim ke proses anak / sub. Sebagai seorang pemula saya tidak bisa menguraikan traphalaman manual jadi saya mungkin melewatkan solusinya.

Saya rasa itulah yang dilakukan program "nyata" seperti Chromium saat Anda mengirimnya SIGTERM

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

Aplikasi dapat menentukan apa yang ingin dilakukan setelah SIGTERM diterima. Sementara sebagian besar aplikasi akan membersihkan sumber daya mereka dan berhenti, beberapa mungkin tidak.

bosa djo
sumber
2
umumnya bersumpah dianggap tidak tepat untuk wacana penuh hormat
kucing
sunting saran disetujui ok, ok selesai, tidak menyenangkan saya mengerti
bosa djo
bukan berarti tidak ada kesenangan yang diizinkan, hanya saja itu dianggap ofensif
kucing
1
@cat Saya sudah memikirkan argumen Anda dan Anda benar, maaf atas tindakan buruk saya
bosa djo

Jawaban:

15

trapbereaksi terhadap sinyal proses panggilan itu sendiri. Tetapi Anda harus memanggilnya sebelum sinyal diterima. Maksud saya, di awal naskah Anda.

Selain itu, jika Anda ingin menggunakan kill -- -$$, yang mengirimkan sinyal juga ke skrip Anda, Anda harus menghapus perangkap sebelum menjalankan kill atau Anda akan berakhir dengan loop kill && trap yang tak terbatas .

Sebagai contoh:

#!/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

Seperti dijelaskan dalam komentar, masalahnya adalah bahwa skrip menerima sinyal tetapi sedang menunggu program tidur untuk berakhir sebelum memproses sinyal yang diterima. Jadi, Anda harus membunuh proses anak (proses tidur dalam kasus ini) untuk menjalankan tindakan perangkap. Anda dapat melakukannya dengan sesuatu seperti berikut:

kill -- -$(pgrep script.sh)

Atau seperti yang dinyatakan dalam komentar:

killall -g script.sh
zuazo
sumber
1
Saya mungkin kehilangan sesuatu karena tidak berfungsi, inilah yang saya lakukan. script.sh &; killall script.sh tetapi tidak melakukan apa-apa.
bosa djo
Saya menjalankan script.sh &; maka saya melakukan bisnis saya; killall script.sh dan itu tidak membunuh script.sh
bosa djo
1
Masalahnya mungkin adalah bahwa skrip menerima sinyal tetapi sedang menunggu program tidur untuk mengakhiri sebelum memprosesnya. Coba dengan ./script.sh & sleep 1 && kill -- -$(pgrep script.sh)mengirim sinyal kill juga ke proses anak skrip Anda.
zuazo
@zuazo Anda harus menambahkan informasi menarik dan penting ini ke jawaban Anda :)
cat
1
Bagus, bosa djo. Saya menambahkan solusi alternatif Anda ke jawaban ;-)
zuazo