Mencoba:
#!/bin/bash
_term() {
echo "Caught SIGTERM signal!"
kill -TERM "$child" 2>/dev/null
}
trap _term SIGTERM
echo "Doing some initial work...";
/bin/start/main/server --nodaemon &
child=$!
wait "$child"
Biasanya, bash
akan mengabaikan sinyal apa pun saat proses anak dieksekusi. Memulai server dengan &
latar belakang akan ke sistem kontrol pekerjaan shell, dengan $!
memegang PID server (untuk digunakan dengan wait
dan kill
). Panggilan wait
kemudian akan menunggu pekerjaan dengan PID yang ditentukan (server) selesai, atau untuk sinyal yang akan dipecat .
Ketika shell menerima SIGTERM
(atau server keluar secara independen), wait
panggilan akan kembali (keluar dengan kode keluar server, atau dengan nomor sinyal + 128 jika sinyal diterima). Setelah itu, jika shell menerima SIGTERM, ia akan memanggil _term
fungsi yang ditentukan sebagai pengendali perangkap SIGTERM sebelum keluar (di mana kami melakukan pembersihan dan menyebarkan sinyal secara manual ke proses server menggunakan kill
).
wait
panggilan selanjutnya diperlukan?exec /bin/start/main/server --nodaemon
(dalam hal ini proses shell diganti dengan proses server dan Anda tidak perlu menyebarkan sinyal apa pun) atau Anda gunakan/bin/start/main/server --nodaemon &
, tetapi kemudianexec
tidak benar-benar bermakna._term()
fungsi Anda haruswait "$child"
lagi. Ini mungkin diperlukan jika Anda memiliki proses pengawasan lain menunggu skrip shell mati sebelum memulai kembali, atau jika Anda juga terjebakEXIT
untuk melakukan pembersihan dan perlu menjalankannya hanya setelah proses anak selesai.exec
, atau Anda ingin mengatur jebakan .Bash tidak meneruskan sinyal seperti SIGTERM untuk memprosesnya saat ini sedang menunggu. Jika Anda ingin mengakhiri skrip Anda dengan memisahkan ke server Anda (memungkinkannya untuk menangani sinyal dan hal lainnya, seolah-olah Anda telah memulai server secara langsung), Anda harus menggunakan
exec
, yang akan menggantikan shell dengan proses yang sedang dibuka :Jika Anda perlu menjaga shell sekitar untuk beberapa alasan (mis. Anda perlu melakukan beberapa pembersihan setelah server berakhir), Anda harus menggunakan kombinasi
trap
,wait
dankill
. Lihat jawaban SensorSmith .sumber
Andreas Veithen menunjukkan bahwa jika Anda tidak perlu kembali dari panggilan (seperti dalam contoh OP) cukup menelepon melalui
exec
perintah sudah cukup ( jawaban @Stuart P. Bentley ). Kalau tidak, "tradisional"trap 'kill $CHILDPID' TERM
(jawaban @ cuonglm) adalah awal, tetapiwait
panggilan benar-benar kembali setelah jebakan pawang berjalan yang masih bisa sebelum proses anak benar-benar keluar. Jadi panggilan "ekstra"wait
disarankan ( jawaban @ user1463361 ).Walaupun ini merupakan peningkatan namun masih memiliki kondisi balapan yang berarti bahwa proses tersebut mungkin tidak pernah keluar (kecuali pemberi sinyal mencoba mengirim sinyal TERM). Jendela kerentanan adalah antara mendaftarkan penangan perangkap dan merekam PID anak.
Berikut ini menghilangkan kerentanan itu (dikemas dalam fungsi untuk digunakan kembali).
sumber
Solusi yang diberikan tidak berfungsi untuk saya karena prosesnya dihancurkan sebelum perintah tunggu benar-benar selesai. Saya menemukan artikel itu http://veithen.github.io/2014/11/16/sigterm-propagation.html , potongan terakhir berfungsi dengan baik dalam kasus aplikasi saya mulai di OpenShift dengan pelari kustom sh. Script sh diperlukan karena saya harus memiliki kemampuan untuk mendapatkan dump thread yang tidak mungkin dalam kasus PID proses Java adalah 1.
sumber