Indaghiamo su tutto Internet e quindi ti diamo la soluzione al tuo dubbio, in caso di dubbio puoi lasciare il dubbio e noi risponderemo perché siamo qui per servirti.
Soluzione:
Soluzione 1:
Risposta trovata.
Per BASH, questo dipende dal file huponexit
opzione shell, che può essere visualizzata e/o impostata utilizzando l'opzione built-in shopt
comando.
Sembra che questa opzione sia disattivata per impostazione predefinita, almeno sui sistemi basati su RedHat.
Maggiori informazioni sulla pagina man di BASH:
La shell esce per impostazione predefinita alla ricezione di un SIGHUP. Prima di uscire, una shell interattiva invia nuovamente il SIGHUP a tutti i lavori, in esecuzione o interrotti. I lavori interrotti vengono inviati SIGCONT per garantire che ricevano il SIGHUP. Per impedire alla shell di inviare il segnale a un particolare lavoro, dovrebbe essere rimosso dalla tabella dei lavori con l'integrato disown (vedere COMANDI INCORPORATI DELLA SHELL sotto) o contrassegnato per non ricevere SIGHUP usando disown -h.
Se l'opzione della shell huponexit è stata impostata con shopt, bash invia un SIGHUP a tutti i job quando esce una shell di login interattiva.
Soluzione 2:
Verrà inviato SIGHUP nei miei test:
Shell1:
[[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
Guscio2:
strace -e trace=signal -p1121
Shell1 Ancora:
[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.
Di nuovo Shell2:
strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached
Perché funziona ancora?:
La programmazione avanzata nell'ambiente Unix di Stevens copre questo argomento nella sezione 9.10: Gruppi di processi orfani. La sezione più rilevante è:
Poiché il gruppo di processi è orfano quando il genitore termina, POSIX.1 richiede che a ogni processo nel gruppo di processi appena orfano che viene arrestato (come lo è il nostro figlio) venga inviato il segnale di riaggancio (SIGHUP) seguito dal segnale di continuazione (SIGCONT ).
Ciò fa sì che il bambino continui, dopo aver elaborato il segnale di riaggancio. L'azione predefinita per il segnale di riaggancio è terminare il processo, quindi dobbiamo fornire un gestore di segnale per catturare il segnale. Ci aspettiamo quindi che printf nella funzione sig_hup appaia prima di printf nella funzione pr_ids.
Soluzione 3:
Ho eseguito alcuni test utilizzando CentOS 7.1 e bash. Nota questo significa huponexit
è off
per impostazione predefinita ed è stato disattivato per la maggior parte dei miei test.
Hai bisogno nohup
quando inizi un lavoro in un terminale, perché se chiudi quel terminale senza uscire dalla shell in modo pulitoil terminale invia a bash il segnale SIGHUP alla shell, che poi lo invia a tutti i figli. Se esci dalla shell in modo pulito, il che significa che il lavoro deve essere già in background in modo da poter digitare exit
o premi Control-D al prompt dei comandi: nessun segnale di alcun tipo viene inviato al lavoro in background da bash.
Test:
Terminale 1
$ echo $$
16779
Terminale 2
$ strace -e signal -p16779
Process 16779 attached
(chiudere il morsetto 1, visto nel morsetto 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 +++
Lavoro 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
Avvialo in background nel Terminale 1:
Terminale 1
$ ./doit.sh &
[1] 22954
Straccialo nel Terminal 2; chiudi il Terminal 1 dopo un paio di loop:
Terminale 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
...
Uscita nel Terminal 3:
Terminale 3
out 1
out 2
out 3
HUP
out 4
out 5
out 6
Tuttavia, se esci bash
, esce semplicemente senza inviare alcun segnale al bambino. Il terminale uscirà perché non ha più un figlio, ma ovviamente non c'è nessuno su HUP perché la shell figlia è già sparita. Il SIGINT
, SIG_BLOCK
e SIG_SETMASK
che vedete sotto sono dovuti al sleep
nel guscio.
Terminale 1
$ ./doit.sh &
26275
Terminale 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
Terminale 3, uscita
out 1
out 2
out 3
out 4
out 5
out 6
È interessante notare che ho impostato huponexit
essere d'accordo shopt -s huponexit; shopt
(quest'ultimo ha effettuato la revisione), quindi ha eseguito l'ultimo test e di nuovo bash non ha inviato alcun segnale al processo in background. Ancora PIÙ interessante, come abbiamo visto bash fatto invia il segnale al processo in background dopo averlo ricevuto da un terminale che si è chiuso in faccia. Sembra come se huponexit
non aveva alcun rapporto in un modo o nell'altro.
Spero che questo rimuova qualsiasi mistero o confusione riguardante almeno l'huppiness di bash, su quando e come viene inviato il segnale HUP. Almeno i miei test erano completamente riproducibili, per me. Sarei interessato a sapere se ci sono altre impostazioni che potrebbero influenzare il comportamento di bash.
E, come sempre, YSMV (Your Shell May Vary).
Addendum 1
Quando eseguo una shell come exec /bin/sh
quindi eseguire lo script come /bin/sh ./doit.sh &
quindi esci dalla shell in modo pulito, non vengono inviati segnali al processo in background e continua a essere eseguito fino al completamento.
Addendum 2
Quando eseguo una shell come exec /bin/csh
quindi eseguire lo script come /bin/sh ./doit.sh &
quindi esci dalla shell in modo pulito, non vengono inviati segnali al processo in background e continua a essere eseguito fino al completamento.
Ricorda qualcosa, che hai la possibilità di aggiungere un'accusa di successo.