Ich habe einige Tests mit CentOS 7.1 und bash durchgeführt. Hinweis : Um dieses Mittel huponexit
ist off
standardmäßig und war für die meisten meiner Tests ab.
Dies ist erforderlich, nohup
wenn Sie einen Job in einem Terminal starten. Wenn Sie dieses Terminal schließen, ohne die Shell sauber zu verlassen , sendet das Terminal das SIGHUP-Signal an die Shell, die es dann an alle untergeordneten Computer sendet. Wenn Sie die Shell sauber beenden, dh der Job muss sich bereits im Hintergrund befinden, damit Sie exit
an der Eingabeaufforderung Control-D eingeben oder drücken können, werden von bash keinerlei Signale an den Hintergrundjob gesendet.
Prüfung:
Terminal 1
$ echo $$
16779
Terminal 2
$ strace -e signal -p16779
Process 16779 attached
(Terminal 1 schließen, siehe 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 +++
Beruf 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
Starte es im Hintergrund in Terminal 1:
Terminal 1
$ ./doit.sh &
[1] 22954
Strace es in Terminal 2; Schließen Sie Terminal 1 nach einigen 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 beenden bash
, wird es einfach beendet, ohne dass ein Signal an das Kind gesendet wird. Das Terminal wird beendet, weil es kein Kind mehr hat, aber natürlich ist niemand für HUP da die Kinderschale bereits weg ist. Die SIGINT
, SIG_BLOCK
und SIG_SETMASK
Sie sehen unten, sind auf die sleep
in der Shell zurückzuführen.
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 machte ich mich huponexit
an shopt -s huponexit; shopt
die Arbeit (letzteres sollte überprüft werden), führte dann den letzten Test durch und schickte erneut bash kein Signal an den Hintergrundprozess . Noch mehr interstingly, wie wir gesehen haben , bash hat das Signal an den Hintergrundprozess senden , nachdem sie es von einem Terminal erhalten , dass in seinem Gesicht geschlossen. Es scheint, als hätte huponexit
es keinen Einfluss auf die eine oder andere Richtung.
Ich hoffe, dies beseitigt jedes Rätsel oder jede Verwirrung in Bezug auf zumindest Bashs Huppiness darüber, 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).
Anhang 1
Wenn ich eine Shell als exec /bin/sh
ausführe, dann das Skript als /bin/sh ./doit.sh &
, dann die Shell sauber beenden, werden keine Signale an den Hintergrundjob gesendet und die Ausführung wird bis zum Abschluss fortgesetzt.
Anhang 2
Wenn ich eine Shell als exec /bin/csh
ausführe, dann das Skript als /bin/sh ./doit.sh &
, dann die Shell sauber beenden, werden keine Signale an den Hintergrundjob gesendet und die Ausführung wird bis zum Abschluss fortgesetzt.
--- 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