Solusi 1:
Jawaban ditemukan.
Untuk BASH, ini tergantung pada huponexit
opsi shell, yang dapat dilihat dan/atau disetel menggunakan shopt
bawaan perintah.
Sepertinya opsi ini dinonaktifkan secara default, setidaknya pada sistem berbasis RedHat.
Info lebih lanjut di halaman manual BASH:
Shell keluar secara default setelah menerima SIGHUP. Sebelum keluar, shell interaktif mengirim ulang SIGHUP ke semua pekerjaan, berjalan atau berhenti. Pekerjaan yang dihentikan dikirim SIGCONT untuk memastikan bahwa mereka menerima SIGHUP. Untuk mencegah shell mengirimkan sinyal ke pekerjaan tertentu, itu harus dihapus dari tabel pekerjaan dengan disown bawaan (lihat PERINTAH BUILTIN SHELL di bawah) atau ditandai untuk tidak menerima SIGHUP menggunakan disown -h.
Jika opsi shell huponexit telah disetel dengan shopt, bash mengirimkan SIGHUP ke semua pekerjaan saat shell login interaktif keluar.
Solusi 2:
Itu akan dikirim SIGHUP dalam pengujian saya:
Shell1:
[[email protected]: ~] ssh localhost
[[email protected]: ~] perl -e sleep &
[1] 1121
[[email protected]: ~] ps
PID TTY TIME CMD
1034 pts/46 00:00:00 zsh
1121 pts/46 00:00:00 perl
1123 pts/46 00:00:00 ps
Shell2:
strace -e trace=signal -p1121
Shell1 Lagi:
[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.
Shell2 Lagi :
strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached
Mengapa masih berjalan?:
Pemrograman Tingkat Lanjut di Lingkungan Unix oleh Stevens membahas hal ini di bawah bagian 9.10:Grup Proses Yatim Piatu. Bagian yang paling relevan adalah:
Karena grup proses menjadi yatim piatu saat induknya berhenti, POSIX.1 mengharuskan setiap proses dalam grup proses yatim piatu yang baru dihentikan (sebagai anak kita) dikirimi sinyal hang-up (SIGHUP) diikuti oleh sinyal lanjutkan (SIGCONT).
Hal ini menyebabkan anak dilanjutkan, setelah memproses sinyal hang-up. Tindakan default untuk sinyal hang-up adalah menghentikan proses, jadi kita harus menyediakan penangan sinyal untuk menangkap sinyal. Oleh karena itu, kami berharap printf dalam fungsi sig_hup muncul sebelum printf dalam fungsi pr_ids.
Solusi 3:
Saya menjalankan beberapa tes menggunakan CentOS 7.1 dan bash. Perhatikan ini berarti huponexit
adalah off
secara default, dan nonaktif untuk sebagian besar pengujian saya.
Anda membutuhkan nohup
ketika Anda memulai pekerjaan di terminal, karena jika Anda menutup terminal itu tanpa keluar dari shell dengan bersih , terminal mengirimkan bash sinyal SIGHUP ke shell, yang kemudian mengirimkannya ke semua anak. Jika Anda keluar dari shell dengan bersih - artinya pekerjaan tersebut harus sudah ada di latar belakang sehingga Anda dapat mengetikkan exit
atau tekan Control-D pada prompt perintah - tidak ada sinyal apa pun yang dikirim ke tugas latar belakang dari bash.
Tes:
Terminal 1
$ echo $$
16779
Terminal 2
$ strace -e signal -p16779
Process 16779 attached
(tutup terminal 1, terlihat di terminal 2):
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16777, si_uid=3000090} ---
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f7ace3d9a00}, {0x456880, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], SA_RESTORER, 0x7f7ace3d9a00}, 8) = 0
kill(16779, SIGHUP) = 0
rt_sigreturn() = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16779, si_uid=3000090} ---
+++ killed by SIGHUP +++
Tugas doit.sh
:
#!/bin/bash
imhupped() {
echo "HUP" >> /tmp/outfile
}
trap imhupped SIGHUP
for i in $(seq 1 6); do echo out $i >> /tmp/outfile; sleep 5; done
Mulai di latar belakang di Terminal 1:
Terminal 1
$ ./doit.sh &
[1] 22954
Strace di Terminal 2; tutup Terminal 1 setelah beberapa putaran:
Terminal 2
$ strace -e signal -p22954
Process 22954 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22980, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn() = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7a5d547a00}, {0x43e4b0, [], SA_RESTORER, 0x7f7a5d547a00}, 8) = 0
...
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=21685, si_uid=3000090} ---
rt_sigreturn() = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=23017, si_status=SIGHUP, si_utime=0, si_stime=0} ---
rt_sigreturn() = 0
...
Keluaran di Terminal 3:
Terminal 3
out 1
out 2
out 3
HUP
out 4
out 5
out 6
Namun, jika Anda keluar dari bash
, itu keluar begitu saja tanpa mengirimkan sinyal apa pun kepada anak sama sekali. Terminal akan keluar karena tidak lagi memiliki anak, tetapi tentu saja tidak ada yang HUP karena cangkang anak sudah hilang. SIGINT
, SIG_BLOCK
dan SIG_SETMASK
Anda lihat di bawah ini disebabkan oleh sleep
di dalam cangkang.
Terminal 1
$ ./doit.sh &
26275
Terminal 2
$ strace -e signal -p26275
Process 26275 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26280, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn() = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
(..."exit" is typed in bash, notice no new signals sent...)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26303, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn() = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
Terminal 3, keluaran
out 1
out 2
out 3
out 4
out 5
out 6
Menariknya, saya menyetel huponexit
untuk menggunakan shopt -s huponexit; shopt
(yang terakhir berbelanja untuk meninjau), kemudian melakukan tes terakhir, dan sekali lagi bash tidak mengirim sinyal ke proses latar belakang . Bahkan LEBIH menarik, seperti yang telah kita lihat bash lakukan mengirim sinyal ke proses latar belakang setelah menerimanya dari terminal yang tertutup di wajahnya. Sepertinya huponexit
tidak ada hubungannya.
Saya harap ini menghilangkan misteri atau kebingungan tentang setidaknya bash's huppiness, tentang kapan dan bagaimana sinyal HUP dikirim. Setidaknya tes saya dapat direproduksi sepenuhnya, bagi saya. Saya akan tertarik untuk mengetahui apakah ada pengaturan lain yang mungkin memengaruhi perilaku bash.
Dan, seperti biasa, YSMV (Cangkang Anda Dapat Bervariasi).
Tambahan 1
Saat saya menjalankan shell sebagai exec /bin/sh
, lalu jalankan skrip sebagai /bin/sh ./doit.sh &
, lalu keluar dari shell dengan bersih, tidak ada sinyal yang dikirim ke tugas latar belakang dan terus berjalan hingga selesai.
Tambahan 2
Saat saya menjalankan shell sebagai exec /bin/csh
, lalu jalankan skrip sebagai /bin/sh ./doit.sh &
, lalu keluar dari shell dengan bersih, tidak ada sinyal yang dikirim ke tugas latar belakang dan terus berjalan hingga selesai.