Jawaban singkat
Dalam bash
(dan dash
) berbagai "status pekerjaan" pesan tidak ditampilkan dari penangan sinyal, tetapi memerlukan pemeriksaan eksplisit. Pemeriksaan ini dilakukan hanya sebelum prompt baru disediakan, mungkin tidak mengganggu pengguna saat dia mengetik perintah baru.
Pesan tidak ditampilkan tepat sebelum prompt setelah kill
ditampilkan mungkin karena prosesnya belum mati - ini adalah kondisi yang sangat mungkin karena kill
merupakan perintah internal shell, jadi sangat cepat untuk mengeksekusi dan tidak perlu forking.
Melakukan percobaan yang sama dengan killall
, sebagai gantinya, biasanya menghasilkan pesan "dibunuh" segera, tanda bahwa waktu / konteks beralih / apa pun yang diperlukan untuk mengeksekusi perintah eksternal menyebabkan penundaan yang cukup lama untuk proses untuk dibunuh sebelum kontrol kembali ke shell .
matteo@teokubuntu:~$ dash
$ sleep 60 &
$ ps
PID TTY TIME CMD
4540 pts/3 00:00:00 bash
4811 pts/3 00:00:00 sh
4812 pts/3 00:00:00 sleep
4813 pts/3 00:00:00 ps
$ kill -9 4812
$
[1] + Killed sleep 60
$ sleep 60 &
$ killall sleep
[1] + Terminated sleep 60
$
Jawaban panjang
dash
Pertama-tama, saya melihat dash
sumber - sumbernya, karena dash
menunjukkan perilaku yang sama dan kodenya jelas lebih sederhana dari itu bash
.
Seperti dikatakan di atas, intinya tampaknya bahwa pesan status pekerjaan tidak dipancarkan dari pengendali sinyal (yang dapat mengganggu aliran kontrol shell "normal"), tetapi mereka adalah konsekuensi dari pemeriksaan eksplisit ( showjobs(out2, SHOW_CHANGED)
panggilan masuk dash
) yang dilakukan hanya sebelum meminta input baru dari pengguna, dalam loop REPL.
Jadi, jika shell diblokir menunggu input pengguna, tidak ada pesan seperti itu yang dipancarkan.
Sekarang, mengapa cek tidak dilakukan sesaat setelah pembunuhan menunjukkan bahwa proses itu benar-benar dihentikan? Seperti dijelaskan di atas, mungkin karena terlalu cepat. kill
adalah perintah internal shell, jadi sangat cepat untuk dieksekusi dan tidak perlu forking, sehingga, segera setelah kill
pemeriksaan dilakukan, prosesnya masih hidup (atau, setidaknya, masih dibunuh).
bash
Seperti yang diharapkan, bash
menjadi cangkang yang jauh lebih kompleks, lebih rumit dan membutuhkan beberapa gdb
fu.
Backtrace ketika pesan itu dipancarkan adalah sesuatu seperti
(gdb) bt
#0 pretty_print_job (job_index=job_index@entry=0, format=format@entry=0, stream=0x7ffff7bd01a0 <_IO_2_1_stderr_>) at jobs.c:1630
#1 0x000000000044030a in notify_of_job_status () at jobs.c:3561
#2 notify_of_job_status () at jobs.c:3461
#3 0x0000000000441e97 in notify_and_cleanup () at jobs.c:2664
#4 0x00000000004205e1 in shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2213
#5 shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2159
#6 0x0000000000423316 in read_token (command=<optimized out>) at /Users/chet/src/bash/src/parse.y:2908
#7 read_token (command=0) at /Users/chet/src/bash/src/parse.y:2859
#8 0x00000000004268e4 in yylex () at /Users/chet/src/bash/src/parse.y:2517
#9 yyparse () at y.tab.c:2014
#10 0x000000000041df6a in parse_command () at eval.c:228
#11 0x000000000041e036 in read_command () at eval.c:272
#12 0x000000000041e27f in reader_loop () at eval.c:137
#13 0x000000000041c6fd in main (argc=1, argv=0x7fffffffdf48, env=0x7fffffffdf58) at shell.c:749
Panggilan yang memeriksa pekerjaan mati & rekan. is notify_of_job_status
(kurang lebih sama dengan showjobs(..., SHOW_CHANGED)
di dash
); # 0 # 1 terkait dengan pekerjaan batinnya; 6-8 adalah kode parser yang dihasilkan yacc; 10-12 adalah loop REPL.
Tempat yang menarik di sini adalah # 4, yaitu dari mana notify_and_cleanup
panggilan itu berasal. Tampaknya bash
, tidak seperti dash
, dapat memeriksa pekerjaan yang dihentikan pada setiap karakter yang dibaca dari baris perintah, tapi inilah yang saya temukan:
/* If the shell is interatctive, but not currently printing a prompt
(interactive_shell && interactive == 0), we don't want to print
notifies or cleanup the jobs -- we want to defer it until we do
print the next prompt. */
if (interactive_shell == 0 || SHOULD_PROMPT())
{
#if defined (JOB_CONTROL)
/* This can cause a problem when reading a command as the result
of a trap, when the trap is called from flush_child. This call
had better not cause jobs to disappear from the job table in
that case, or we will have big trouble. */
notify_and_cleanup ();
#else /* !JOB_CONTROL */
cleanup_dead_jobs ();
#endif /* !JOB_CONTROL */
}
Jadi, dalam mode interaktif itu sengaja untuk menunda pemeriksaan sampai prompt baru disediakan, mungkin tidak mengganggu pengguna memasukkan perintah. Adapun mengapa cek tidak melihat proses mati saat menampilkan prompt baru segera setelah kill
, penjelasan sebelumnya berlaku (proses belum mati).
pid="$(sh -c 'cat "$fileName" |less & echo ${!}')"
tetapi kurang muncul