Lösung 1:
Antwort gefunden.
Für BASH hängt dies vom huponexit
ab Shell-Option, die mit dem eingebauten shopt
angezeigt und/oder eingestellt werden kann Befehl.
Sieht so aus, als ob diese Option standardmäßig deaktiviert ist, zumindest auf RedHat-basierten Systemen.
Weitere Informationen auf der BASH-Manpage:
Die Shell wird standardmäßig beim Empfang eines SIGHUP beendet. Vor dem Beenden sendet eine interaktive Shell das SIGHUP erneut an alle laufenden oder angehaltenen Jobs. Gestoppte Jobs erhalten SIGCONT, um sicherzustellen, dass sie das SIGHUP erhalten. Um zu verhindern, dass die Shell das Signal an einen bestimmten Job sendet, sollte er mit dem eingebauten Disown aus der Jobs-Tabelle entfernt werden (siehe SHELL BUILTIN COMMANDS unten) oder mit disown -h so markiert werden, dass er kein SIGHUP empfängt.
Wenn die Shell-Option huponexit mit shopt gesetzt wurde, sendet bash ein SIGHUP an alle Jobs, wenn eine interaktive Login-Shell beendet wird.
Lösung 2:
Es wird in meinen Tests SIGHUP gesendet:
Schale1:
[[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
Wieder Shell1:
[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.
Wieder Shell2 :
strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached
Warum läuft es noch?:
Advanced Programming in the Unix Environment von Stevens behandelt dies in Abschnitt 9.10:Verwaiste Prozessgruppen. Der relevanteste Abschnitt ist:
Da die Prozessgruppe verwaist ist, wenn der Elternteil endet, verlangt POSIX.1, dass jedem Prozess in der neu verwaisten Prozessgruppe, der gestoppt wird (wie unser Kind), das Auflegesignal (SIGHUP) gefolgt vom Fortsetzungssignal (SIGCONT) gesendet wird.
Dies bewirkt, dass das Kind nach der Verarbeitung des Auflegesignals fortgesetzt wird. Die Standardaktion für das Auflegesignal besteht darin, den Prozess zu beenden, sodass wir einen Signalhandler bereitstellen müssen, um das Signal abzufangen. Wir erwarten daher, dass printf in der Funktion sig_hup vor printf in der Funktion pr_ids erscheint.
Lösung 3:
Ich habe einige Tests mit CentOS 7.1 und Bash durchgeführt. Beachten Sie, dass dies huponexit
bedeutet ist off
standardmäßig und war für die meisten meiner Tests ausgeschaltet.
Sie benötigen nohup
wenn Sie einen Job in einem Terminal starten, denn wenn Sie dieses Terminal schließen, ohne die Shell sauber zu verlassen , das Terminal sendet bash das SIGHUP-Signal an die Shell, die es dann an alle untergeordneten Elemente sendet. Wenn Sie die Shell sauber verlassen, muss der Job bereits im Hintergrund laufen, damit Sie exit
eingeben können oder drücken Sie Strg-D an der Eingabeaufforderung – es werden keinerlei Signale von bash an den Hintergrundjob gesendet.
Test:
Terminal 1
$ echo $$
16779
Terminal 2
$ strace -e signal -p16779
Process 16779 attached
(Terminal 1 schließen, in Terminal 2 gesehen):
--- 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 +++
Stelle 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
Starten Sie es im Hintergrund im Terminal 1:
Terminal 1
$ ./doit.sh &
[1] 22954
Verfolgen Sie es in Terminal 2; schließen Sie Terminal 1 nach ein paar Schleifen:
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
...
Ausgabe in Klemme 3:
Terminal 3
out 1
out 2
out 3
HUP
out 4
out 5
out 6
Wenn Sie jedoch bash
beenden , wird es einfach beendet, ohne überhaupt ein Signal an das Kind zu senden. Das Terminal wird beendet, weil es kein Kind mehr hat, aber natürlich gibt es niemanden für HUP, weil die Kind-Shell bereits weg ist. Die SIGINT
, SIG_BLOCK
und SIG_SETMASK
die Sie unten sehen, sind auf sleep
zurückzuführen in der Schale.
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
Klemme 3, Ausgang
out 1
out 2
out 3
out 4
out 5
out 6
Interessanterweise habe ich huponexit
eingestellt eingeschaltet sein mit shopt -s huponexit; shopt
(letzteres shopt zur Überprüfung), führte dann den letzten Test durch und wieder bash sendete kein Signal an den Hintergrundprozess . Sogar noch interessanter, wie wir gesehen haben, dass bash tat Senden Sie das Signal an den Hintergrundprozess, nachdem er es von einem Terminal empfangen hat, das ihm ins Gesicht geschlossen hat. Es scheint, als ob huponexit
hatte auf die eine oder andere Weise keine Bedeutung.
Ich hoffe, dies beseitigt alle Rätsel oder Verwirrungen zumindest in Bezug auf die Freude von bash, wann und wie das HUP-Signal gesendet wird. Zumindest waren meine Tests für mich vollständig reproduzierbar. Mich würde interessieren, ob es irgendwelche anderen Einstellungen gibt, die das Verhalten von bash beeinflussen könnten.
Und wie immer YSMV (Your Shell May Vary).
Nachtrag 1
Wenn ich eine Shell als exec /bin/sh
ausführe , und führen Sie das Skript dann als /bin/sh ./doit.sh &
aus , dann beenden Sie die Shell sauber, es werden keine Signale an den Hintergrundjob gesendet und er wird bis zum Ende weiter ausgeführt.
Nachtrag 2
Wenn ich eine Shell als exec /bin/csh
ausführe , und führen Sie das Skript dann als /bin/sh ./doit.sh &
aus , dann beenden Sie die Shell sauber, es werden keine Signale an den Hintergrundjob gesendet und er wird bis zum Ende weiter ausgeführt.