Linux tue-t-il les processus de fond si nous fermons le terminal à partir duquel il a commencé?
j'ai un système embarqué, sur lequel je ne telnet
puis-je exécuter une application en arrière-plan:
./app_name &
maintenant si je ferme mon terminal et faire telnet
depuis un autre terminal et si je vérifie alors je peux voir que ce processus est toujours en cours.
Pour vérifier ce que j'ai écrit un petit programme:
#include<stdio.h>
main()
{
while(1);
}
j'ai lancé ce programme dans mon PC linux local en arrière-plan et j'ai fermé le terminal.
maintenant, quand j'ai vérifié pour ce processus d'autres terminal puis j'ai trouvé que ce processus a également été tué.
Ma question est:
- Pourquoi un comportement non défini pour le même type de processus?
- dont elle dépend?
- est-il dépendant de la version de Linux?
4 réponses
qui devrait supprimer des emplois?
normalement, les travaux de premier plan et de fond sont tués par SIGHUP
envoyé par noyau ou shell dans des circonstances différentes.
Quand noyau envoyer SIGHUP
?
Kernel envoie SIGHUP
contrôle de processus:
- pour terminal réel (matériel): lorsque la déconnexion est détectée dans un pilote de terminal, p.ex. sur raccrocher sur un modem ligne;
- pseudoterminal (pty): lorsque le dernier descripteur référençant le côté maître de Pty est fermé, par exemple lorsque vous fermez la fenêtre du terminal.
Kernel envoie SIGHUP
pour les autres groupes de processus:
- groupe du procédé de premier plan lorsque contrôle de processus prend fin;
- orphelins de groupe de processus, quand il devient orphelin et cela a arrêté les membres.
processus de contrôle est le leader de session qui a établi la connexion au terminal de contrôle.
typiquement, le processus de contrôle est votre shell. Donc, pour résumer:
- noyau envoie
SIGHUP
à l'interpréteur de commandes lorsque le vrai ou le pseudoterminal est déconnecté / fermé; - noyau envoie
SIGHUP
au premier plan groupe de processus lorsque le shell se termine; - noyau envoie
SIGHUP
à orphaned process group s'il contient des processus arrêtés.
Notez que le noyau ne pas envoyer SIGHUP
à background process group s'il ne contient aucun processus arrêté.
Quand bash
envoyer SIGHUP
?
Bash envoie SIGHUP
emplois (premier plan et arrière-plan):
- lorsqu'il reçoit
SIGHUP
, et c'est un shell interactif (et contrôle du travail prise en charge est activée au moment de la compilation); - quand il sort, c'est un shell de connexion interactif et
huponexit
option est définie (et contrôle du travail le support est activé à la compilation).
Voir plus de détails ici.
Notes:
bash
ne pas envoyerSIGHUP
aux emplois supprimés de la liste des emplois en utilisantdisown
;- les processus ont commencé à utiliser
nohup
ignorerSIGHUP
.
Plus de détails ici.
Qu'en est-il des autres coquilles?
habituellement, les coquillages se propagent SIGHUP
. Générer SIGHUP
à la sortie normale est moins fréquente.
Telnet ou SSH
sous telnet ou SSH, ce qui suit devrait se produire quand la connexion est fermée (par exemple quand vous fermez telnet
fenêtre sur le PC):
- le client est tué;
- le serveur détecte que le client, la connexion est fermée;
- serveur ferme master côté de pty;
- kernel détecte que master pty est fermé et envoie
SIGHUP
bash
; bash
reçoitSIGHUP
, envoieSIGHUP
pour tous les emplois et prend fin;- chaque emploi reçoit
SIGHUP
et se termine.
Problème
je peux reproduire votre numéro en utilisant bash
et telnetd
busybox
ou dropbear
SSH server:parfois, arrière-plan de l'emploi n'est pas recevoir SIGHUP
(et ne se termine pas) lorsque la connexion client est fermée.
Il semble qu'un condition se produit lorsque le serveur (telnetd
ou dropbear
) ferme le côté maître de pty:
- normalement,
bash
reçoitSIGHUP
et supprime immédiatement les travaux en arrière-plan (comme prévu) et la termine; - mais parfois,
bash
détecteEOF
sur l'esclave côté de pty avant manutentionSIGHUP
.
Quand bash
détecte EOF
, il se termine immédiatement par défaut sans envoyer SIGHUP
. Et le travail de fond continue!
Solution
Il est possible de configurer bash
envoyer SIGHUP
sur sortie normale (y compris EOF
):
S'assurer que
bash
est lancé en tant que shell de connexion.huponexit
uniquement pour les shells de login, autant que je sache.le shell de connexion est activé par
-l
ou trait d'Union principalargv[0]
. Vous pouvez configurertelnetd
exécuter/bin/bash -l
ou mieux/bin/login
qui appelle/bin/sh
dans le shell de connexion mode.par exemple:
telnetd -l /bin/login
Activer
huponexit
option.par exemple:
shopt -s huponexit
Tapez ceci dans
bash
session à chaque fois ou l'ajouter à.bashrc
ou/etc/profile
.
Pourquoi la course se produire?
bash
débloque les signaux seulement quand c'est sûr, et les bloque quand une section de code ne peut pas être interrompue en toute sécurité par un gestionnaire de signal.
Ces sections critiques appeler points d'interruption de temps en temps, et si le signal est reçu lorsqu'une section critique est exécutée, son gestionnaire est retardé jusqu'à ce que le prochain point d'interruption se produise ou que la section critique soit sortie.
Vous pouvez commencer à creuser à partir de quit.h
dans le code source.
Ainsi, il semble que dans notre cas bash
reçoit parfois SIGHUP
quand c'est dans une section critique. SIGHUP
gestionnaire l'exécution est retardée, et bash
lit EOF
et se termine avant sortie de la section critique ou appel au prochain point d'interruption.
Référence
- "Poste De Contrôle" section dans le manuel officiel de Glibc.
- Chapitre 34, "les Groupes de Processus, les Sessions, et le Contrôle du Travail" de "L'Linux Programming Interface" livre.
pour comprendre complètement ce qui se passe, vous devez entrer dans unix
internes un peu.
Lorsque vous exécutez une commande comme ceci
./app_name &
app_name
est envoyé à background process group. Vous pouvez le vérifier sur unix
groupes de processus ici
quand vous fermez bash
avec la sortie normale, il déclenche SIGHUP
signal de raccrochage à tous ses emplois. Quelques informations sur unix
le contrôle du travail est ici.
afin de garder votre application en marche lorsque vous quittez bash
vous devez rendre votre application immunisée au signal de raccrocher avec nohup
utilitaire.
nohup-exécuter une commande insensible aux raccroches, avec une sortie vers un non-tty
et finalement c'est comme ça que vous devez le faire.
nohup app_name & 2> /dev/null;
quand vous fermez le terminal, shell envoie SIGHUP
pour tous les processus d'arrière-plan – et qui les tue. Cela peut être supprimé de plusieurs façons, notamment:
nohup
Lorsque vous exécutez le programme avec nohup
il attrape SIGHUP
et rediriger la sortie du programme.
$ nohup app &
renier
disown
dit à shell de ne pas envoyer SIGHUP
$ app &
$ disown
Est-il dépendant de la version de linux?
cela dépend de votre coquille. Ci-dessus s'applique au moins pour bash.
AFAIK dans les deux cas, le processus devrait être tué. Afin d'éviter cela, vous devez émettre un nohup comme suit:
> nohup ./my_app &
de cette façon votre processus continuera d'exécuter. Probablement la partie telnet est due à un BUG similaire à celui-ci: