Saya menggunakan Ubuntu 14.04 dan saya mengalami perilaku ini yang sepertinya tidak saya mengerti:
- Jalankan
yes
perintah (dalam shell default: Bash ) - Ketik CtrlZuntuk berhenti
yes
- Lari
jobs
. Keluaran:
[1]+ Stopped yes
- Lari
kill -9 %1
untuk berhentiyes
. Keluaran:
[1]+ Stopped yes
- Lari
jobs
. Keluaran:
[1]+ Stopped yes
Ini ada di Ubuntu yang 3.16.0-30-generic
berjalan di mesin virtual paralel.
Mengapa kill -9
perintah saya tidak menghentikan perintah ya ? Saya pikir SIGKILL tidak dapat ditangkap atau diabaikan? Dan bagaimana saya bisa menghentikan perintah yes ?
shell
job-control
s1m0n
sumber
sumber
uname -a
) tolongLinux ubuntu 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
. Saya menjalankan Ubuntu di Parallels Desktop.(signal)
sehingga Anda dapat membedakannya.Jawaban:
Sinyal diblokir untuk proses yang ditangguhkan. Di terminal:
Di terminal kedua:
Di terminal pertama:
Namun
SIGKILL
tidak dapat diblokir. Melakukan hal yang sama dengankillall -9 yes
dari terminal kedua segera memberikan ini diyes
terminal:Akibatnya jika
kill -9 %1
tidak menghentikan proses segera makabash
tidak benar-benar mengirim sinyal sampai Andafg
proses, atau Anda telah menemukan bug di kernel.sumber
SIGTSTP
(yang merupakan versi yang dapat diblokirSIGSTOP
) ke proses aktif. Ini menempatkan proses dalam keadaan beku di mana kernel tidak akan menjadwalkannya. Itu juga menghambat pemrosesan sinyal (kecuali untukSIGCONT
sinyal yang tidak membekukan proses) dan karenanya mencegah proses agar tidak segera dimatikan.SIGTERM
diblokir, tetapiSIGKILL
tidak. Bagaimanapun, menurut komentar dari OP, masalahnya tampaknyajobs
tidak mendeteksi bahwa proses telah mati, bukan proses yang tidak dibunuhkill -9 %1
.SIGKILL
tidak dapat diblokir, tidak ada jaminan bahwa itu akan dikirimkan dalam waktu yang berarti. Jika suatu proses ditangguhkan sambil menunggu pemblokiran I / O, misalnya,SIGKILL
tidak akan tiba sampai proses bangun. Ini bisa berpotensi tidak pernah, jika tidak ada I / O terjadi.Jangan panik.
Tidak ada yang funky terjadi. Tidak ada bug kernel di sini. Ini adalah perilaku normal dari shell Bourne Again dan sistem operasi multitasking.
Yang perlu diingat adalah bahwa suatu proses membunuh dirinya sendiri , bahkan sebagai respons terhadapnya
SIGKILL
. Apa yang terjadi di sini adalah bahwa cangkang Bourne Again sedang menyelesaikan beberapa hal sebelum proses yang dikatakannya untuk membunuh dirinya sendiri untuk membunuh dirinya sendiri.Pertimbangkan apa yang terjadi dari titik di mana
yes
telah dihentikanSIGTSTP
dan Anda baru saja menjalankankill
perintah dengan shell Bourne Again:SIGKILL
keyes
proses.yes
Proses dijadwalkan untuk berjalan dan segera membunuh dirinya sendiri.Alasan Anda melihat satu hal dan orang lain melihat yang lain adalah perlombaan sederhana antara dua proses yang siap dijalankan, pemenangnya sepenuhnya bergantung pada hal-hal yang bervariasi baik dari mesin ke mesin dan dari waktu ke waktu. Beban sistem membuat perbedaan, seperti halnya fakta bahwa CPU Anda virtual.
Dalam kasus yang menarik, detail dari langkah # 2 adalah ini:
kill
itu menandai entri di tabel tugasnya sebagai memerlukan pesan pemberitahuan dicetak pada titik berikutnya yang tersedia.kill
perintah, dan tepat sebelum mencetak prompt lagi memeriksa untuk melihat apakah itu harus mencetak pesan pemberitahuan tentang pekerjaan apa pun.yes
Proses tidak memiliki kesempatan untuk membunuh dirinya sendiri lagi, jadi sejauh shell yang bersangkutan pekerjaan masih dalam keadaan berhenti. Jadi shell mencetak garis status pekerjaan "Dihentikan" untuk pekerjaan itu, dan mengatur ulang pemberitahuannya yang tertunda.yes
Proses akan dijadwalkan dan membunuh dirinya sendiri.Poin-poin penting adalah:
SIGKILL
tidak ajaib. Proses memeriksa sinyal yang tertunda saat kembali ke mode aplikasi dari mode kernel, yang terjadi pada akhir kesalahan halaman, interupsi (tidak bersarang), dan panggilan sistem. Satu-satunya hal yang istimewa adalah bahwa kernel tidak mengizinkan tindakan sebagai tanggapanSIGKILL
selain bunuh diri langsung dan tanpa syarat, tanpa kembali ke mode aplikasi. Yang penting, proses-proses harus membuat transisi mode-ke-aplikasi-mode dan dijadwalkan untuk berjalan untuk merespons sinyal.set -o notify
). Mereka dicetak ketika shell berikutnya mencapai titik dalam siklus eksekusi yang memeriksa untuk melihat apakah ada notifikasi yang tertunda.kill
dan sekali olehSIGCHLD
penangan sinyal. Ini berarti bahwa seseorang dapat melihat dua pesan jika shell berjalan sebelumyes
proses dijadwal ulang untuk bunuh diri; satu pesan "Dihentikan" dan satu pesan "Dibunuh"./bin/kill
program tidak memiliki akses ke tabel pekerjaan internal shell; jadi Anda tidak akan melihat perilaku seperti itu dengan/bin/kill
. Bendera yang menunggu pemberitahuan hanya diatur satu kali, olehSIGCHLD
pawang.kill
yangyes
proses dari shell lain.sumber
jobs
dan shell masih melihat prosesnya hidup. Itu akan menjadi satu kondisi lomba penjadwalan yang luar biasa panjang. :)jobs
perintah multiply setelahkill
semua yang masih menunjukkan proses hanya berhenti. Namun Anda mengilhami saya untuk terus bereksperimen dan saya menemukan ini: pesan[1]+ Terminated yes
dicetak segera setelah saya menjalankan perintah eksternal lain (bukan shell yang dibangun sepertiecho
ataujobs
). Jadi saya bisa menjalankanjobs
sebanyak yang saya suka dan terus mencetak[1]+ Stopped yes
. Tetapi segera setelah saya menjalankanls
misalnya, Bash mencetak[1]+ Terminated yes
jobs
tidak menyadari bahwa prosesnya telah benar-benar mati ... Tidak yakin apa yang harus dilakukan tentang status yang diperbarui dengan menjalankan perintah lain.Sesuatu yang funky mungkin terjadi pada sistem Anda, pada resep saya resep Anda bekerja dengan baik dengan dan tanpa
-9
:Dapatkan pid
jobs -p
dan coba untuk membunuhnyaroot
.sumber
kill
perintah internal bash Anda bekerja lebih keras dan memeriksa apakah pekerjaan itu dibekukan (Anda mungkin ingin mencoba mencari tahu PID pekerjaan itu dan membunuhnya menggunakan ituenv kill <pid>
. Dengan begitu Anda akan menggunakankill
perintah yang sebenarnya dan bukan bash builtin.which kill /usr/bin/kill
which
bukan bash-builtin, jadiwhich <anything>
akan selalu memberi Anda jalan ke perintah yang sebenarnya. Tapi coba membandingkankill --help
vs/usr/bin/kill --help
.kill
.Yang Anda amati adalah bug dalam versi bash ini.
kill -9 %1
tidak membunuh pekerjaan itu segera. Anda dapat mengamati itu denganps
. Anda dapat melacak proses bash untuk melihat kapankill
panggilan sistem dipanggil, dan melacak subproses untuk melihat kapan ia menerima dan memproses sinyal. Lebih menarik lagi, Anda dapat pergi dan melihat apa yang terjadi pada proses.Di terminal lain:
Subproses adalah zombie . Sudah mati: yang tersisa hanyalah entri dalam tabel proses (tetapi tidak ada memori, kode, buka file, dll.). Entri dibiarkan sampai induknya memperhatikan dan mengambil status keluar dengan memanggil
wait
panggilan sistem atau salah satu saudara kandungnya .Shell interaktif seharusnya memeriksa anak-anak yang mati dan menuai mereka sebelum mencetak prompt (kecuali jika dikonfigurasi sebaliknya). Versi bash ini gagal melakukannya dalam beberapa keadaan:
Anda mungkin mengharapkan bash untuk melaporkan "Dibunuh" segera setelah mencetak prompt setelah
kill
perintah, tetapi itu tidak dijamin, karena ada kondisi balapan. Sinyal dikirimkan secara tidak sinkron:kill
panggilan sistem kembali segera setelah kernel menentukan proses pengiriman sinyal, tanpa menunggu pengirimannya. Mungkin saja, dan dalam praktiknya, bash mempunyai waktu untuk memeriksa status subprosesnya, menemukan bahwa itu masih belum mati (wait4
tidak melaporkan kematian anak), dan mencetak bahwa prosesnya masih dihentikan. Apa yang salah adalah bahwa sebelum prompt berikutnya, sinyal telah dikirim (ps
melaporkan bahwa prosesnya mati), namun bash masih belum memanggilwait4
(kita bisa melihat itu bukan hanya karena masih melaporkan pekerjaan sebagai "Berhenti", tetapi karena zombie masih ada di tabel proses). Bahkan, bash hanya menuai zombie saat berikutnya perlu memanggilwait4
, ketika menjalankan beberapa perintah eksternal lainnya.Bugnya berselang dan saya tidak bisa mereproduksinya saat bash dilacak (mungkin karena ini adalah kondisi balapan di mana bash perlu bereaksi cepat). Jika sinyal dikirim sebelum bash memeriksa, semuanya terjadi seperti yang diharapkan.
sumber