GNU/Linux >> Tutoriels Linux >  >> Linux

Les processus d'arrière-plan obtiennent-ils un SIGHUP lors de la déconnexion ?

Solution 1 :

Réponse trouvée.

Pour BASH, cela dépend du huponexit option shell, qui peut être visualisée et/ou définie à l'aide de l'élément shopt intégré commande.

Il semble que cette option soit désactivée par défaut, du moins sur les systèmes basés sur RedHat.

Plus d'informations sur la page de manuel BASH :

Le shell se ferme par défaut à la réception d'un SIGHUP. Avant de quitter, un shell interactif renvoie le SIGHUP à tous les travaux, en cours d'exécution ou arrêtés. Les travaux arrêtés reçoivent SIGCONT pour s'assurer qu'ils reçoivent le SIGHUP. Pour empêcher le shell d'envoyer le signal à un travail particulier, il doit être supprimé de la table des travaux avec la commande intégrée disown (voir COMMANDES INTÉGRÉES DU SHELL ci-dessous) ou marqué pour ne pas recevoir SIGHUP en utilisant disown -h.

Si l'option de shell huponexit a été définie avec shopt, bash envoie un SIGHUP à toutes les tâches lorsqu'un shell de connexion interactif se termine.

Solution 2 :

Il sera envoyé SIGHUP dans mes tests :

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

Shell2 :

strace -e trace=signal -p1121

Shell1 à nouveau :

[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

Shell2 à nouveau :

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

Pourquoi fonctionne-t-il toujours ? :
La programmation avancée dans l'environnement Unix par Stevens couvre cela dans la section 9.10 :Groupes de processus orphelins. La section la plus pertinente étant :

Étant donné que le groupe de processus est orphelin lorsque le parent se termine, POSIX.1 exige que chaque processus du groupe de processus nouvellement orphelin qui est arrêté (comme notre enfant) reçoive le signal de raccrochage (SIGHUP) suivi du signal de poursuite (SIGCONT).

Cela entraîne la poursuite de l'enfant après le traitement du signal de raccrochage. L'action par défaut pour le signal de raccrochage est de terminer le processus, nous devons donc fournir un gestionnaire de signal pour capter le signal. Nous nous attendons donc à ce que le printf dans la fonction sig_hup apparaisse avant le printf dans la fonction pr_ids.

Solution 3 :

J'ai effectué des tests avec CentOS 7.1 et bash. Notez que cela signifie huponexit est off par défaut, et était désactivé pour la majorité de mes tests.

Vous avez besoin de nohup lorsque vous démarrez une tâche dans un terminal, car si vous fermez ce terminal sans quitter proprement le shell , le terminal envoie bash le signal SIGHUP au shell, qui l'envoie ensuite à tous les enfants. Si vous quittez le shell proprement, cela signifie que le travail doit déjà être en arrière-plan pour que vous puissiez taper exit ou appuyez sur Contrôle-D à l'invite de commande - aucun signal d'aucune sorte n'est envoyé à la tâche d'arrière-plan depuis bash.

Test :

Terminal 1

$ echo $$
16779

Terminal 2

$ strace -e signal -p16779
Process 16779 attached

(fermer le terminal 1, vu dans le 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 +++

Emploi 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

Démarrez-le en arrière-plan dans le Terminal 1 :

Terminal 1

$ ./doit.sh &
[1] 22954

Tracez-le dans le Terminal 2 ; fermez le Terminal 1 après quelques boucles :

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
...

Sortie dans le terminal 3 :

Terminal 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

Cependant, si vous quittez bash , il sort simplement sans envoyer aucun signal à l'enfant. Le terminal se fermera car il n'a plus d'enfant, mais bien sûr il n'y a personne pour HUP car le shell enfant est déjà parti. Le SIGINT , SIG_BLOCK et SIG_SETMASK que vous voyez ci-dessous sont dus au sleep dans le shell.

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

Terminal 3, sortie

out 1
out 2
out 3
out 4
out 5
out 6

Fait intéressant, j'ai mis huponexit être avec shopt -s huponexit; shopt (ce dernier doit passer en revue), puis a effectué le dernier test, et à nouveau bash n'a envoyé aucun signal au processus d'arrière-plan . Encore PLUS intéressant, comme nous l'avons vu bash l'a fait envoyer le signal au processus d'arrière-plan après l'avoir reçu d'un terminal qui s'est fermé devant lui. Il semble que huponexit n'avait aucune incidence dans un sens ou dans l'autre.

J'espère que cela lèvera tout mystère ou confusion concernant au moins le bonheur de bash, quant au moment et à la manière dont le signal HUP est envoyé. Au moins mes tests étaient complètement reproductibles, pour moi. Je serais intéressé de savoir s'il existe d'autres paramètres susceptibles d'affecter le comportement de bash.

Et, comme toujours, YSMV (Your Shell May Vary).

Addendum 1

Lorsque j'exécute un shell en tant que exec /bin/sh , puis exécutez le script en tant que /bin/sh ./doit.sh & , puis quittez le shell proprement, aucun signal n'est envoyé au travail d'arrière-plan et il continue de s'exécuter jusqu'à la fin.

Addendum 2

Lorsque j'exécute un shell en tant que exec /bin/csh , puis exécutez le script en tant que /bin/sh ./doit.sh & , puis quittez le shell proprement, aucun signal n'est envoyé au travail d'arrière-plan et il continue de s'exécuter jusqu'à la fin.


Linux
  1. La ligne de commande s'écrase lorsque les commandes deviennent trop longues

  2. Comment tuer tous les processus d'arrière-plan dans zsh ?

  3. Comment obtenir errno lorsque epoll_wait renvoie EPOLLERR ?

  4. Pourquoi LXC quand il y a Linux-vserver ?

  5. Obtenir la charge moyenne à l'exclusion des processus agréables

Recevoir une notification lorsqu'une tâche de terminal est terminée

Comment démarrer automatiquement une session d'écran sous Linux lors de la connexion

Démarrage automatique de la session Tmux sur le système distant lors de la connexion via SSH

Exécutez des processus d'arrière-plan sous Linux à l'aide de la commande Screen

Comment envoyer des processus en arrière-plan sous Linux

Comment Linux alloue-t-il la bande passante entre les processus ?