Я провел несколько тестов, используя CentOS 7.1 и bash. Обратите внимание, что это означает, huponexit
что off
по умолчанию оно отключено для большинства моих тестов.
Вам нужно, nohup
когда вы запускаете задание в терминале, потому что, если вы закрываете этот терминал, не выходя из оболочки чисто , терминал отправляет bash сигнал SIGHUP в оболочку, которая затем отправляет его всем дочерним элементам. Если вы аккуратно выходите из оболочки - значит, задание уже должно быть в фоновом режиме, чтобы вы могли вводить exit
или нажимать Control-D в командной строке - никакие сигналы любого рода не отправляются в фоновое задание из bash.
Тест:
Терминал 1
$ echo $$
16779
Терминал 2
$ strace -e signal -p16779
Process 16779 attached
(закрыть терминал 1, видно в терминале 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 +++
Работа 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
Запустите его в фоновом режиме в терминале 1:
Терминал 1
$ ./doit.sh &
[1] 22954
Разместите это в Терминале 2; закройте Терминал 1 после нескольких петель:
Терминал 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
...
Выход в Терминал 3:
Терминал 3
out 1
out 2
out 3
HUP
out 4
out 5
out 6
Однако, если вы выходите bash
, он просто выходит, вообще не посылая никакого сигнала ребенку. Терминал выйдет, потому что у него больше нет дочернего, но, конечно, нет никого, кто мог бы подключиться к HUP, потому что дочерняя оболочка уже пропала. SIGINT
, SIG_BLOCK
И SIG_SETMASK
вы видите ниже, в связи с sleep
в оболочке.
Терминал 1
$ ./doit.sh &
26275
Терминал 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
Терминал 3, выход
out 1
out 2
out 3
out 4
out 5
out 6
Интересно, что я установил , huponexit
чтобы быть с shopt -s huponexit; shopt
(последняя shopt к обзору), затем выполняется последнее испытание, и снова удар не посылали сигнал фонового процесса . Даже MORE Interstingly, как мы уже видели Баш сделал послать сигнал на фоновый процесс после того, как он получил его от терминала , который был закрыт в его лице. Кажется, что huponexit
не имеет никакого отношения ни к одному, ни к другому.
Я надеюсь, что это устранит любую тайну или путаницу относительно, по крайней мере, счастья Баша, о том, когда и как отправляется сигнал HUP. По крайней мере, мои тесты были полностью воспроизводимы для меня. Мне было бы интересно узнать, есть ли другие параметры, которые могут влиять на поведение bash.
И, как всегда, YSMV (ваша оболочка может меняться).
Приложение 1
Когда я запускаю оболочку как exec /bin/sh
, затем запускаю сценарий как /bin/sh ./doit.sh &
, а затем аккуратно выхожу из оболочки, никакие сигналы не отправляются в фоновое задание и он продолжает выполняться до завершения.
Приложение 2
Когда я запускаю оболочку как exec /bin/csh
, затем запускаю сценарий как /bin/sh ./doit.sh &
, а затем аккуратно выхожу из оболочки, никакие сигналы не отправляются в фоновое задание и он продолжает выполняться до завершения.
--- 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