Saya mencoba membuat skrip shell sehingga menjalankan proses latar belakang, dan ketika saya Ctrlcskrip shell, itu membunuh anak-anak, lalu keluar.
Yang terbaik yang berhasil saya lakukan adalah ini. Tampaknya kill 0 -INT
juga membunuh skrip sebelum menunggu terjadi, sehingga skrip shell mati sebelum anak-anak selesai.
Ada ide tentang bagaimana saya bisa membuat skrip shell ini menunggu anak-anak mati setelah mengirim INT
?
#!/bin/bash
trap 'killall' INT
killall() {
echo "**** Shutting down... ****"
kill 0 -INT
wait # Why doesn't this wait??
echo DONE
}
process1 &
process2 &
process3 &
cat # wait forever
Jawaban:
kill
Perintah Anda mundur.Seperti banyak perintah UNIX, opsi yang dimulai dengan minus harus didahulukan, sebelum argumen lain.
Jika kamu menulis
ia melihat
-INT
opsi, dan mengirimSIGINT
ke0
(0
adalah nomor khusus yang berarti semua proses dalam grup proses saat ini).Tetapi jika Anda menulis
ia melihat
0
, memutuskan tidak ada lagi opsi, jadi gunakanSIGTERM
secara default. Dan mengirimkan bahwa untuk kelompok proses saat ini, sama seperti jika Anda lakukan(Ini juga akan mencoba mengirim
SIGTERM
ke-INT
, yang akan menyebabkan kesalahan sintaks, tetapi mengirimSIGTERM
ke0
pertama, dan tidak pernah sampai sejauh itu.)Jadi skrip utama Anda adalah
SIGTERM
sebelum menjalankanwait
danecho DONE
.Menambahkan
di atas, tepat setelah
dan jalankan lagi untuk membuktikan ini.
Seperti yang ditunjukkan Stephane Chazelas, anak-anak Anda yang berlatar belakang (
process1
, dll.) Akan mengabaikannyaSIGINT
secara default.Bagaimanapun, saya pikir pengiriman
SIGTERM
akan lebih masuk akal.Akhirnya, saya tidak yakin apakah
kill -process group
dijamin pergi ke anak-anak dulu. Mengabaikan sinyal saat mematikan mungkin merupakan ide yang bagus.Jadi coba ini:
sumber
Sayangnya, perintah yang dimulai di latar belakang diatur oleh shell untuk mengabaikan SIGINT, dan lebih buruk lagi, mereka tidak bisa mengabaikannya dengan
trap
. Kalau tidak, yang harus Anda lakukan adalahKarena process1 dan process2 akan mendapatkan SIGINT ketika Anda menekan Ctrl-C karena mereka adalah bagian dari grup proses yang sama yang merupakan grup proses foreground terminal.
Kode di atas akan bekerja dengan pdksh dan zsh yang dalam hal itu tidak sesuai dengan POSIX.
Dengan shell lain, Anda harus menggunakan sesuatu yang lain untuk mengembalikan handler default untuk SIGINT seperti:
atau gunakan sinyal yang berbeda seperti SIGTERM.
sumber
Bagi mereka yang hanya ingin membunuh suatu proses dan menunggu sampai mati, tetapi tidak tanpa batas :
Itu menunggu maksimal 60 detik per jenis sinyal.
Peringatan: Jawaban ini sama sekali tidak terkait dengan menangkap sinyal mematikan dan mengirimkannya.
Ini memilih aplikasi untuk dibunuh berdasarkan nama atau argumen. Simpan tanda kurung untuk huruf pertama nama aplikasi untuk menghindari pencocokan grep itu sendiri.
Dengan beberapa perubahan, Anda dapat langsung menggunakan PID atau lebih sederhana
pidof process_name
daripadaps
pernyataan.Detail kode: Grep terakhir adalah untuk mendapatkan PID tanpa spasi tambahan.
sumber
Jika yang Anda inginkan adalah mengelola beberapa proses latar belakang, mengapa tidak menggunakan fitur kontrol pekerjaan bash?
sumber
Jadi saya bermain-main dengan ini juga. Di Bash, Anda dapat mendefinisikan fungsi dan melakukan hal-hal yang mewah dengan itu. Rekan kerja saya dan saya menggunakan
terminator
, jadi untuk eksekusi batch kita biasanya menelurkan sejumlah besar terminator windows jika kita ingin melihat output (kurang elegan daripadatmux
tab, tetapi Anda dapat menggunakan antarmuka yang lebih mirip GUI haha).Inilah pengaturan yang saya buat, serta contoh hal-hal yang dapat Anda jalankan:
Lari itu
Sunting @ Maxim, baru saja melihat saran Anda, yang membuatnya menjadi lebih sederhana! Terima kasih!
sumber