CentOS 7.1 및 bash를 사용하여 몇 가지 테스트를 실행했습니다. 이 방법을 참고 huponexit
입니다 off
기본적으로 내 테스트의 대부분을 벗어났다.
당신은 필요 nohup
터미널에서 작업을 시작할 때 때문에, 당신은 가까운 깨끗하게 쉘을 종료하지 않고 터미널한다는 경우 는 터미널이 모든 아이들에게 보내는 쉘에 SIGHUP 신호를 bash는 보냅니다. 쉘을 깨끗하게 종료하면 작업이 이미 백그라운드에 있어야 exit
명령 프롬프트에서 Control-D를 입력 하거나 칠 수 있습니다-bash 에서 백그라운드 작업으로 어떤 종류의 신호도 보내지 않습니다.
테스트:
터미널 1
$ echo $$
16779
터미널 2
$ strace -e signal -p16779
Process 16779 attached
(터미널 2에서 볼 수있는 터미널 1을 닫으십시오) :
--- 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에서 in니다. 몇 번의 루프 후 터미널 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
흥미롭게도, I 세트 huponexit
로에있을 shopt -s huponexit; shopt
다음 (검토 후자 shopt 내부) 최종 검사를 행하고, 다시 배시 백그라운드 프로세스에 어떠한 신호도 전송되지 . 훨씬 더 간결하게, 우리가 bash 가 신호를 닫은 터미널에서 신호를받은 후 백그라운드 프로세스로 신호를 보내는 것을 보았습니다 . 그것은 huponexit
어떤 식 으로든 베어링을 가지고 있지 않은 것처럼 보입니다 .
이것이 HUP 신호가 언제 어떻게 전송되는지에 관한 적어도 bash의 행복에 관한 수수께끼 나 혼란을 제거하기를 바랍니다. 적어도 내 테스트는 완전히 재현 가능했습니다. bash의 동작에 영향을 줄 수있는 다른 설정이 있는지 알고 싶습니다.
그리고 항상 그렇듯이 YSMV (Shell May Vary).
부록 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