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?
19
demandé sur gavv 2015-09-25 14:00:51

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 SIGHUPcontrô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:

  • bashne pas envoyer SIGHUP aux emplois supprimés de la liste des emplois en utilisant disown;
  • les processus ont commencé à utiliser nohupignorerSIGHUP.

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):

  1. le client est tué;
  2. le serveur détecte que le client, la connexion est fermée;
  3. serveur ferme master côté de pty;
  4. kernel détecte que master pty est fermé et envoie SIGHUPbash;
  5. bash reçoit SIGHUP, envoie SIGHUP pour tous les emplois et prend fin;
  6. chaque emploi reçoit SIGHUP et se termine.

Problème

je peux reproduire votre numéro en utilisant bash et telnetdbusybox 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:

  1. normalement, bash reçoit SIGHUP et supprime immédiatement les travaux en arrière-plan (comme prévu) et la termine;
  2. mais parfois, bash détecte EOF sur l'esclave côté de pty avant manutention SIGHUP.

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 configurer telnetd 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.
31
répondu gavv 2017-05-23 12:03:08

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;

4
répondu deimus 2015-09-25 11:28:58

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.

3
répondu pacholik 2017-06-09 15:25:18

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:

https://bugzilla.redhat.com/show_bug.cgi?id=89653

3
répondu rkachach 2017-06-11 07:23:46