Oturumu kapatırken arka plan işlemleri SIGHUP alıyor mu?


21

Bu, bu sorunun bir devamıdır .

Biraz daha test yaptım; bunun fiziksel konsolda mı yoksa SSH ile mi yapıldığının bir önemi yok gibi görünüyor, bu da sadece SCP ile gerçekleşmiyor; Ben de test ettim cat /dev/zero > /dev/null. Davranış tamamen aynıdır:

  • Kullanarak arka planda bir süreç başlatın &(veya kullanarak Başladıktan sonra arka planda koymak CTRL-Zve bg); Bu yapıldıktan kullanmadannohup .
  • Oturumu Kapat.
  • Tekrar oturum açın.
  • Süreç hala orada, mutlu bir şekilde çalışıyor ve şimdi doğrudan bir çocuğu init.

Eğer gönderilirse SCP ve CAT çıkışlarını hemen onaylayabilirim SIGHUP; Bunu kullanarak test ettim kill -HUP.

Yani, gerçekten SIGHUP oturum kapatıldıktan sonra, en azından arka plan işlemlerine gönderilmiyor gibi görünüyor (bariz nedenlerden ötürü bir ön plan ile test edilemiyor).

Bu bana başlangıçta VMware ESX 3.5'in (RedHat tabanlı) hizmet konsolu ile oldu, ancak tam olarak CentOS 5.4'te çoğaltmayı başardım.

Yine soru şu: arka planda çalışıyor olsalar bile, oturum kapatıldıktan sonra bir SIGHUP süreçlere gönderilmemeli mi? Bu neden olmuyor?


Düzenle

straceKyle'ın cevabına göre kontrol ettim .
Beklediğim gibi, işlem başlatıldığı kabuktan çıkış yaparken herhangi bir sinyal almıyor . Bu hem sunucunun konsolunu kullanırken hem de SSH aracılığıyla olur.


CentOS 7.1'de Bash kullanıldığında, basit bir kabuk komut dosyası döngüsü ön planda bırakılırsa, ancak terminal öldürülürse SIGHUP alır; başka bir terminal gösterir strace: --- 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

Bir arka plan komut dosyası da öyle. Döngü bir uykuda beklerken terminalin kapalı olduğunu unutmayın. --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=13944, si_uid=3000090} --- +++ killed by SIGHUP +++
Mike S

Testler için cevabımı görün. İlginçtir, nedeniyle davranışlarında hiçbir değişiklik görmedim huponexit.
Mike S

Yanıtlar:


26

Yanıt bulundu.

BASH için bu huponexit, yerleşik shoptkomut kullanılarak görüntülenebilen ve / veya ayarlanabilen kabuk seçeneğine bağlıdır .

Görünüşe göre bu seçenekler en azından RedHat tabanlı sistemlerde varsayılan olarak kapalıdır.

BASH man sayfası hakkında daha fazla bilgi :

Bir SIGHUP alındıktan sonra kabuk varsayılan olarak çıkar. Çıkıştan önce, etkileşimli bir kabuk SIGHUP'u çalışan veya durdurulan tüm işlere yeniden gönderir. Durdurulmuş işler SIGHUP aldıklarından emin olmak için SIGCONT'a gönderilir. Kabuğun sinyali belirli bir işe göndermesini önlemek için, reddedilen yerleşik ile iş tablosundan kaldırılmalıdır (aşağıdaki SHELL BUILTIN KOMUTLARI bölümüne bakın) veya -h disown kullanarak SIGHUP almama olarak işaretlenmelidir.

Huponexit kabuk seçeneği shopt ile ayarlandıysa, etkileşimli bir oturum açma kabuğu çıktığında bash tüm işlere bir SIGHUP gönderir.


4
Doğrulanmış. Bir "çıkış", "oturum kapatma" veya CTL-D gerçekleştirdiğimde, alt proc (iş) bir görüş alma (hem root hem de reg kullanıcısı) almayacaktı. Ancak ben bash mevcut örneğini öldürmek için "-HUP $$ öldürmek" yaptığımda çocuk süreçleri bir iç çekme DID aldı. Daha sonra huponexit ayarladım ve alt işlem çıkışta SIGHUP aldı.
CarpeNoctem

3

Testlerimde SIGHUP gönderilecek:

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

Kabuk 2:

strace -e trace=signal -p1121

Shell1 Tekrar:

[kbrandt@kbrandt-opadmin: ~] exit
zsh: you have running jobs.
[kbrandt@kbrandt-opadmin: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

Shell2 Tekrar :

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

Neden hala çalışıyor ?
: Stevens'ın Unix Ortamında İleri Düzey Programlama, bunu bölüm 9.10: Yetim İşlem Grupları başlığı altında ele almaktadır. En alakalı bölüm:

Üst grup sona erdiğinde işlem grubu yetim kaldığından POSIX.1, yeni yetim kalan işlem grubundaki (çocuğumuz gibi) durdurulan her işlemin askıya alma sinyali (SIGHUP) ve devam sinyali (SIGCONT) gönderilmesini gerektirir ).

Bu, kapatma sinyalini işledikten sonra çocuğun devam etmesine neden olur. Kapatma sinyali için varsayılan eylem, işlemi sonlandırmaktır, bu nedenle sinyali yakalamak için bir sinyal işleyici sağlamalıyız. Bu nedenle sig_hup işlevindeki printf'in pr_ids işlevindeki printf'den önce görünmesini bekliyoruz.


Ama burada açıkça bir İPEK gönderdiniz; İşlemi başlattığınız kabuktan çıkış yaptığınızda neler olduğu hakkında konuşuyordum.
Massimo

Ben işler hakkında bir uyarı almak rağmen çıkış yazın, ancak sonra tekrar exit yazın aynı sonuçları. Bunu ZSH ile test ettim.
Kyle Brandt

BASH kullanıyorum ve bu muhtemelen kabuğa bağlı. Ama BASH gerektiğini kapalı oturum açarken ... alt süreçlere SIGHUP göndermek
Massimo

Bash, iş durdurulursa SIGCONT'u açıkça gönderir, ancak iş durdurulmazsa hiçbir şey göndermediğini onaylarım.
Kyle Brandt

CentOS 7.1'de Bash kullanarak, işlemime başka bir pencerede durdurulmuş bir SIGTERM alıyorum: 1.) Basit kabuk komut dosyasını (yankı ve uyku ile döngü) başlatın, 2.) Control-Z it, 3) başka bir pencere, 4) orijinal terminalden çıkın. İşlerimin çalıştığından şikayet ediyor, sonra straceğimden çıktıktan sonra: $ 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 +++ Garip, kesinlikle Stevens'dan alıntılanan bölüme uygun değil.
Mike S

2

CentOS 7.1 ve bash kullanarak bazı testler yaptım. Bu araçlar Not huponexitolduğu offvarsayılan olarak, ve benim testlerin çoğu için kapalı idi.

İhtiyacınız nohupBir terminalde bir iş başlattığınızda, çünkü sen yakın temiz kabuk çıkmadan terminali ki eğer , Terminal sonra tüm çocuklara gönderir kabuğuna SIGHUP sinyalini bash gönderir. Kabuktan temiz bir şekilde çıkarsanız exit, komut isteminde Control-D yazabilmeniz veya bu komutu vurabilmeniz için işin zaten arka planda olması gerekir; bash'dan arka plan işine herhangi bir sinyal gönderilmez.

Ölçek:

Terminal 1

$ echo $$
16779

Terminal 2

$ strace -e signal -p16779
Process 16779 attached

(terminal 2'de görülen terminal 1'i kapatın):

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

Meslek 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

Terminal 1'deki arka planda başlatın:

Terminal 1

$ ./doit.sh &
[1] 22954

Terminal 2'ye yerleştirin; birkaç döngüden sonra Terminal 1'i kapatın:

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

Terminal 3'teki çıkış:

Terminal 3

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

Ancak, çıkarsanız bash, çocuğa hiç sinyal göndermeden çıkar. Terminal artık bir çocuğu olmadığı için çıkacak, ancak elbette HUP'a kimse yok çünkü çocuk kabuğu zaten gitti. SIGINT, SIG_BLOCKVe SIG_SETMASKaşağıda gördüğünüz nedeniyle sleepkabukta.

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, çıkış

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

İlginç bir şekilde, (ikinci gözden geçirme için gözden geçirme) huponexitile açık olmaya ayarladım shopt -s huponexit; shopt, daha sonra son testi gerçekleştirdim ve tekrar bash arka plan işlemine sinyal göndermedi . Hatta DAHA interstingly, biz bash gördüğümüz gibi yaptım onun yüzüne kapattığını bir terminalden onu aldıktan sonra arka plan sürecine sinyal gönderecek. Öyle huponexitya da böyle bir yönü yoktu gibi görünüyor .

Umarım bu en azından bash'ın huppiness, HUP sinyalinin ne zaman ve nasıl gönderildiği ile ilgili herhangi bir gizemi veya karışıklığı ortadan kaldırır. En azından benim testlerim tamamen tekrarlanabilirdi. Bash'ın davranışını etkileyebilecek başka ayarların olup olmadığını bilmek isterim.

Ve her zaman olduğu gibi, YSMV (Kabuğunuz Değişebilir).

Zeyilname 1

Bir kabuk olarak exec /bin/shçalıştırdığımda, komut dosyasını farklı bir şekilde çalıştırdığımda, /bin/sh ./doit.sh &kabuktan temiz bir şekilde çıkar, arka plan işine hiçbir sinyal gönderilmez ve tamamlanmaya devam eder.

Zeyilname 2

Bir kabuk olarak exec /bin/cshçalıştırdığımda, komut dosyasını farklı bir şekilde çalıştırdığımda, /bin/sh ./doit.sh &kabuktan temiz bir şekilde çıkar, arka plan işine hiçbir sinyal gönderilmez ve tamamlanmaya devam eder.


0

Csh kullanıyorum ve arka plan işlemleri oturumu kapattığımda devam ediyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.