Apakah proses latar belakang mendapatkan SIGHUP saat keluar?

21

Ini adalah tindak lanjut dari pertanyaan ini .

Saya sudah menjalankan beberapa tes lagi; sepertinya itu benar-benar tidak masalah jika ini dilakukan di konsol fisik atau melalui SSH, juga tidak terjadi hanya dengan SCP; Saya juga mengujinya dengan cat /dev/zero > /dev/null. Perilaku ini persis sama:

  • Mulai proses di latar belakang menggunakan &(atau letakkan di latar belakang setelah mulai menggunakan CTRL-Zdan bg); ini dilakukan tanpa menggunakannohup .
  • Keluar.
  • Logon lagi.
  • Prosesnya masih ada, berjalan dengan gembira, dan sekarang adalah anak langsung dari init.

Saya dapat mengkonfirmasi SCP dan CAT segera berhenti jika mengirim SIGHUP; Saya menguji ini menggunakan kill -HUP.

Jadi, sepertinya SIGHUP tidak dikirim saat keluar, setidaknya untuk proses latar belakang (tidak dapat menguji dengan latar depan karena alasan yang jelas).

Ini terjadi pada saya pada awalnya dengan konsol layanan VMware ESX 3.5 (yang didasarkan pada RedHat), tetapi saya dapat meniru persis pada CentOS 5.4.

Pertanyaannya adalah, sekali lagi: bukankah SIGHUP harus dikirim ke proses, bahkan jika itu berjalan di latar belakang, setelah log off? Mengapa ini tidak terjadi?


Edit

Aku mengeceknya strace, sesuai jawaban Kyle.
Seperti yang saya harapkan, proses tidak mendapatkan sinyal apa pun ketika keluar dari shell tempat diluncurkan. Ini terjadi saat menggunakan konsol server dan melalui SSH.

Massimo
sumber
Menggunakan Bash pada CentOS 7.1, loop skrip shell sederhana akan mendapatkan SIGHUP jika dibiarkan di latar depan, tetapi terminal terbunuh; strace dari terminal lain menunjukkan: --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=10676, si_uid=3000090} --- rt_sigreturn() = -1 EINTR (Interrupted system call) rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
Mike S
Begitu juga skrip latar belakang. Perhatikan bahwa terminal ditutup ketika loop sedang menunggu tidur. Shell TIDAK keluar:--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=13944, si_uid=3000090} --- +++ killed by SIGHUP +++
Mike S
Lihat jawaban saya untuk tes. Menariknya, saya melihat tidak ada perubahan perilaku karena huponexit.
Mike S

Jawaban:

26

Jawaban ditemukan.

Untuk BASH, ini tergantung pada huponexitopsi shell, yang dapat dilihat dan / atau diatur menggunakan shoptperintah bawaan.

Sepertinya opsi ini tidak aktif secara default, setidaknya pada sistem berbasis RedHat.

Info lebih lanjut tentang 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 mengirim sinyal ke pekerjaan tertentu, itu harus dihapus dari tabel pekerjaan dengan builtin yang disown (lihat SHELL BUILTIN PERINTAH di bawah) atau ditandai untuk tidak menerima SIGHUP menggunakan disown -h.

Jika opsi shell huponexit telah diatur dengan shopt, bash mengirimkan SIGHUP ke semua pekerjaan ketika shell login interaktif keluar.

Massimo
sumber
4
Diverifikasi. Ketika saya melakukan "keluar", "logout", atau CTL-D proc anak (pekerjaan) tidak akan menerima sighup (baik pengguna root dan reg). Namun ketika saya melakukan "kill -HUP $$" untuk membunuh instance bash saat ini, proses anak DID menerima desahan. Saya kemudian mengatur huponexit dan proses anak menerima SIGHUP saat keluar.
CarpeNoctem
3

Itu akan dikirim SIGHUP dalam pengujian saya:

Shell1:

[kbrandt@kbrandt-opadmin: ~] ssh localhost
[kbrandt@kbrandt-opadmin: ~] perl -e sleep & 
[1] 1121
[kbrandt@kbrandt-opadmin: ~] 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:

[kbrandt@kbrandt-opadmin: ~] exit
zsh: you have running jobs.
[kbrandt@kbrandt-opadmin: ~] 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 bagian 9.10: Grup Proses yang Yatim. Bagian yang paling relevan adalah:

Karena grup proses menjadi yatim piatu ketika induk berakhir, POSIX.1 mengharuskan setiap proses dalam grup proses yang baru menjadi yatim yang dihentikan (seperti anak kami) dikirim sinyal hang-up (SIGHUP) diikuti oleh sinyal lanjutan (SIGCONT ).

Ini menyebabkan anak untuk melanjutkan, setelah memproses sinyal hang-up. Tindakan default untuk sinyal hang-up adalah menghentikan proses, jadi kami harus menyediakan penangan sinyal untuk menangkap sinyal. Karena itu kami mengharapkan printf dalam fungsi sig_hup muncul sebelum printf pada fungsi pr_ids.

Kyle Brandt
sumber
Tapi Anda secara eksplisit mengirim SIGHUP ke sini; Saya sedang berbicara tentang apa yang terjadi ketika Anda keluar dari shell tempat Anda memulai proses.
Massimo
Hasil yang sama ketika saya mengetik keluar, meskipun saya mendapat peringatan tentang pekerjaan, tetapi kemudian ketik keluar lagi. Saya menguji ini dengan ZSH.
Kyle Brandt
Saya menggunakan BASH, dan ini mungkin tergantung pada shell. Tapi BASH harus mengirim SIGHUP ke proses anak saat logout ...
Massimo
Bash mengirim SIGCONT rupanya jika pekerjaan itu dihentikan, tetapi saya mengkonfirmasi itu tidak mengirim apa-apa jika pekerjaan itu tidak dihentikan.
Kyle Brandt
Menggunakan Bash pada CentOS 7.1, saya mendapatkan SIGTERM yang dikirim ke proses saya berhenti di jendela lain: 1.) Mulai skrip shell sederhana (loop dengan gema dan tidur), 2.) Control-Z it, 3) strace proses di jendela lain, 4) keluar dari terminal asli. Mengeluh bahwa saya telah menjalankan pekerjaan, kemudian setelah keluar dari pertunjukan saya: $ strace -e signal -p1705 Process 1705 attached --- stopped by SIGTSTP --- --- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=791, si_uid=3000090} --- +++ killed by SIGTERM +++ Aneh, jelas tidak sesuai dengan bagian yang dikutip dari Stevens.
Mike S
2

Saya menjalankan beberapa tes menggunakan CentOS 7.1 dan bash. Perhatikan ini berarti huponexitsecara offdefault, dan tidak aktif untuk sebagian besar tes saya.

Anda perlu nohupketika 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 mengetik exitatau menekan Control-D pada prompt perintah - tidak ada sinyal apa pun yang dikirim ke pekerjaan latar belakang dari bash.

Uji:

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 +++

Pekerjaan 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 loop:

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
...

Output di Terminal 3:

Terminal 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

Namun, jika Anda keluar bash, itu hanya keluar tanpa mengirim sinyal apa pun kepada anak sama sekali. Terminal akan keluar karena tidak lagi memiliki anak, tetapi tentu saja tidak ada orang yang dapat HUP karena shell anak sudah hilang. Itu SIGINT, SIG_BLOCKdan SIG_SETMASKAnda lihat di bawah ini disebabkan oleh sleepdi shell.

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 mulai huponexitmenggunakan shopt -s huponexit; shopt(shopt terakhir untuk meninjau), kemudian melakukan tes terakhir, dan lagi-lagi bash tidak mengirim sinyal ke proses latar belakang . Bahkan LEBIH BANYAK bersilangan, seperti yang kita lihat bash memang mengirim sinyal ke proses latar belakang setelah menerimanya dari terminal yang tertutup di wajahnya. Sepertinya huponexittidak ada kaitannya dengan satu atau lain cara.

Saya harap ini menghilangkan setiap misteri atau kebingungan mengenai setidaknya hashiness bash, tentang kapan dan bagaimana sinyal HUP dikirim. Setidaknya tes saya benar-benar dapat direproduksi, untuk saya. Saya akan tertarik untuk mengetahui apakah ada pengaturan lain yang mungkin memengaruhi perilaku bash.

Dan, seperti biasa, YSMV (Shell Anda Dapat Bervariasi).

Adendum 1

Ketika saya menjalankan shell as exec /bin/sh, kemudian jalankan script as /bin/sh ./doit.sh &, lalu keluar shell dengan bersih, tidak ada sinyal yang dikirim ke pekerjaan latar belakang dan terus berjalan hingga selesai.

Tambahan 2

Ketika saya menjalankan shell as exec /bin/csh, kemudian jalankan script as /bin/sh ./doit.sh &, lalu keluar shell dengan bersih, tidak ada sinyal yang dikirim ke pekerjaan latar belakang dan terus berjalan hingga selesai.

Mike S
sumber
0

Saya menggunakan proses csh dan latar belakang terus berjalan bersama saat saya logoff.

Chris S
sumber