Ingin memperbaiki pertanyaan ini? Tambahkan detail dan klarifikasi masalahnya dengan mengedit postingan ini.
Ditutup 3 tahun yang lalu.
Perbaiki pertanyaan ini
Untuk memahami
Jika Bash menunggu perintah untuk diselesaikan dan menerima sinyal untuk
mana jebakan telah ditetapkan, jebakan tidak akan dijalankan hingga
perintah selesai.Saat Bash menunggu perintah asinkron melalui fitur wait bawaan ,
penerimaan sinyal yang perangkapnya telah ditetapkan akan menyebabkan
builtin tunggu untuk segera kembali dengan status keluar lebih besar dari
128, segera setelah perangkap dijalankan.
dari manual Bash,
Saya menjalankan yang berikut:
-
Dalam dua contoh saya, SIGINT (dikirim dengan Ctrl-C) mengakhiri
pekerjaan latar depan (kasus pertama dalam kutipan) dan pekerjaan latar belakang
(kasus kedua dalam kutipan) keduanya segera, tanpa menunggu untuk
mereka selesaikan.Apakah kalimat pertama dalam kutipan berarti bahwa jika Bash menjalankan
pekerjaan latar depan dan menerima sinyalSIGINT
, perangkap sinyalSIGINT
, jika disetel, akan dijalankan hingga perintah selesai?
Jika ya, mengapa pada contoh pertama saya, apakahctrl-C
buat pekerjaan latar depan
segera ada sebelum dapat diselesaikan?$ sleep 10000 # a foreground job ^C $ sleep 10000 & # a background job [1] 21219 $ wait 21219 ^C $ echo $? 130
-
Apa yang dimaksud dengan “sinyal yang telah memasang jebakan” maksudnya,
-
sinyal
arg
yang perangkapnya telah ditentukan melaluitrap arg sigspec
, atau -
sinyal yang tidak diabaikan, atau
-
sinyal yang perangkapnya bukan yang default?
Dalam contoh di bagian 1 saya, saya tidak menyiapkan jebakan untuk SIGINT, jadi sinyalnya memiliki
penangan defaultnya (yang keluar dari loop eksekusi apa pun). Apakah sebuah
sinyal memiliki pengendali defaultnya dianggap memiliki jebakan yang
telah dipasang? -
-
Saya membuat jebakan untuk
SIGINT
, tetapictrl-C
akan membuat perintah
berikut keluar sebelum selesai. Jadi apakah ini bertentangan dengan
kalimat pertama dalam kutipan saya?$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $
Sebelum menyetel jebakan untuk
SIGINT
,ctrl-C
juga akan membuat
perintah yang sama keluar sebelum menyelesaikan. Jadi apakah ini bertentangan dengan
kalimat pertama dalam kutipan saya?$ bash -c 'sleep 10; echo "$?"' ^C
-
Bisakah Anda memberikan beberapa contoh untuk menjelaskan apa arti kedua kalimat dalam
kutipan tersebut?
Terima kasih.
Jawaban yang Diterima:
Apa yang dimaksud dengan "sinyal yang telah memasang jebakan"?
Itu adalah sinyal yang penangannya telah ditentukan (dengan trap 'handling code' SIG
) di mana kode penanganan tidak kosong karena akan menyebabkan sinyal diabaikan.
Jadi sinyal yang memiliki disposisi default bukanlah sinyal yang telah dipasang jebakan.
Beberapa kutipan di posting Anda juga berlaku untuk sinyal yang memiliki disposisi default, meskipun jelas bukan bagian tentang menjalankan perangkap , karena tidak ada jebakan yang ditentukan untuk mereka.
Manual berbicara tentang pengiriman sinyal ke shell , bukan ke perintah yang Anda jalankan dari shell itu.
1.
Jika Bash menunggu perintah untuk diselesaikan dan menerima sinyal bahwa jebakan telah ditetapkan, jebakan tidak akan dijalankan sampai perintah selesai.
(1)
mengapa dalam contoh pertama saya, apakah ctrl-C membuat pekerjaan latar depan segera keluar sebelum dapat diselesaikan
Jika Anda menjalankan sleep 10
pada prompt shell interaktif , shell akan menempatkan pekerjaan itu di latar depan (melalui ioctl()
pada perangkat tty yang memberi tahu disiplin baris terminal grup proses mana yang menjadi latar depan), jadi hanya sleep
akan mendapatkan SIGINT pada ^C
dan shell interaktif tidak akan , jadi tidak berguna untuk menguji perilaku itu.
-
Shell induk, karena bersifat interaktif, tidak akan menerima SIGINT karena prosesnya tidak berada dalam grup proses latar depan.
-
Setiap perintah bebas menangani sinyal sesuka mereka.
sleep
tidak melakukan sesuatu yang khusus dengan SIGINT, jadi akan mendapatkan disposisi default (berhenti) kecuali SIGINT diabaikan saat startup.
(2) Jika Anda menjalankan sleep 10
dalam cangkang non-interaktif ,
bash -c 'sleep 10; echo "$?"'
Keduanya bash
noninteraktif shell dan sleep
akan menerima SIGINT saat Anda menekan Ctrl-C.
Jika bash
keluar langsung, itu bisa meninggalkan sleep
perintah berjalan tanpa pengawasan di latar belakang jika kebetulan mengabaikan atau menangani sinyal SIGINT. Jadi sebagai gantinya,
bash
seperti kebanyakan shell lainnya, blok penerimaan sinyal (setidaknya beberapa sinyal) saat menunggu perintah.- Pengiriman dilanjutkan setelah perintah keluar (di mana jebakan dieksekusi). Itu juga menghindari perintah dalam perangkap untuk dijalankan secara bersamaan dengan perintah lain.
Dalam contoh di atas, sleep
akan mati setelah SIGINT, jadi bash
tidak perlu menunggu lama untuk menangani SIGINT-nya sendiri (disini mati karena saya tidak menambahkan trap
di SIGINT).
(3) saat Anda menekan Ctrl+C saat menjalankan shell noninteraktif:
bash -c 'sh -c "trap "" INT; sleep 3"; echo "$?"'
(tanpa trap
pada SIGINT) bash
tidak dibunuh oleh SIGINT. bash
, seperti beberapa shell lainnya memperlakukan SIGINT dan SIGQUIT secara khusus. Mereka menerapkan keluar menunggu dan kooperatif perilaku yang dijelaskan di https://www.cons.org/cracauer/sigint.html (dan diketahui menyebabkan beberapa gangguan seperti skrip yang memanggil perintah penanganan SIGINT yang tidak dapat diinterupsi dengan ^C
)
(4) Untuk menguji dengan benar, Anda harus menjalankan bash
non-interaktif bahwa memiliki perangkap SIGINT yang disetel dan memanggil perintah yang tidak langsung mati pada SIGINT seperti:
bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 3"'
bash
sedang menunggu sh
yang memiliki (bersama dengan sleep
) SIGINT diabaikan (karena trap "" INT
), jadi SIGINT tidak akan mematikan sleep
atau sh
. bash
tidak mengabaikan SIGINT, tetapi penanganannya ditunda hingga sh
kembali. Anda melihat Ouch
sedang ditampilkan, bukan pada Ctrl+C , tapi setelah sleep
dan sh
telah dihentikan secara normal.
Perhatikan bahwa trap
perintah menetapkan perangkap untuk sinyal untuk shell yang sama di mana ia berjalan. Jadi ketika trap
perintah dijalankan di luar shell noninteractive dan di shell induk,
$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $
bash
yang noninteraktif , dan sleep
perintah tidak akan mewarisi trap
dari cangkang induk. Penangan sinyal hilang saat menjalankan perintah yang berbeda (execve()
menghapus seluruh ruang alamat proses termasuk kode pawang). Setelah execve()
, sinyal yang memiliki penangan yang ditentukan kembali ke disposisi default, yang diabaikan tetap diabaikan.
Selain itu, di sebagian besar shell, trap
s juga direset di sub-kulit.
2.
Saat Bash menunggu perintah asinkron melalui fitur wait bawaan , penerimaan sinyal yang perangkapnya telah ditetapkan akan menyebabkan fitur tunggu segera kembali dengan status keluar lebih besar dari 128, segera setelah perangkap dijalankan.
Saat menggunakan wait
secara eksplisit , wait
diinterupsi oleh sinyal apa pun yang memiliki jebakan (dan jelas juga sinyal yang membunuh cangkang sama sekali).
Itu membuat sulit untuk mendapatkan status keluar dari suatu perintah secara andal ketika ada sinyal yang terjebak :
$ bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 10" & wait "$!"; echo "$?"'
^COuch
130
Dalam hal ini, sleep
dan sh
tidak dibunuh oleh SIGINT (karena mereka mengabaikannya). Masih wait
kembali dengan 130
status keluar karena sinyal (SIGINT) diterima saat menunggu sh
. Anda harus mengulang wait "$!"
sampai sh
benar-benar berakhir untuk mendapatkan sh
status keluar.