Pourquoi mon processus est toujours en cours d'exécution après ma déconnexion?

10

Une fois connecté ssh, je tape cette commande dans bash:

sleep 50000000000000 &

Ensuite, je kill -9le sleepprocessus parent du processus (c.-à bash-d.). Ensuite, la fenêtre du terminal se déconnecte simultanément.

Lorsque je me reconnecte, je constate que le sleepprocessus est toujours en cours.

Question : Pourquoi le sleepprocessus peut-il survivre lorsque je me déconnecte et que le terminal est fermé? Dans mon esprit, tout sauf les démons et les nohupprogrammes sera tué lors de la déconnexion. Si sleeppeut survivre de cette façon, cela signifie-t-il que je peux utiliser cette méthode à la place de la nohupcommande?

matou
la source
3
&va bifurquer le processus en arrière-plan (comme le démon) et continue de fonctionner même si vous êtes déconnecté.
Aizuddin Zali

Réponses:

6

Tl; dr:

Pourquoi le sleepprocessus peut-il survivre lorsque je me déconnecte et que le terminal est fermé? Dans mon esprit, tout sauf les démons et les nohupprogrammes sera tué lors de la déconnexion. Si sleeppeut survivre de cette façon, cela signifie-t-il que je peux utiliser cette méthode à la place de la nohupcommande?

À moins que l' bashinstance engendrée par sshn'ait l' huponexitoption définie, aucun processus ne sera interrompu de quelque manière que ce soit à la sortie / déconnexion, et lorsque l' huponexitoption est définie, l'utilisation kill -9sur le shell n'est pas une bonne alternative à l'utilisation nohupsur les processus enfants du shell; nohupsur le shell, les processus enfants les protégeront toujours contre les SIGHUP qui ne proviennent pas du shell, et même lorsque cela n'est pas important, il nohupfaut toujours le préférer car cela permet de terminer le shell avec élégance.


Il bashy a une option appelée huponexitqui, si elle est définie, fera de bashSIGHUP ses enfants à la sortie / déconnexion;

Dans les bash instances interactives sans connexion , comme dans une bashinstance générée par gnome-terminal, cette option est ignorée; qu'il huponexitsoit réglé ou non, bashles enfants de 'S ne seront jamais SIGHUPpés bashà la sortie;

Dans les instances de connexion interactive bash, comme dans une bashinstance engendrée par ssh, cette option n'est pas ignorée (mais elle n'est pas définie par défaut); s'il huponexitest défini, bashles enfants de SIGHUP seront suivis par bashà la sortie / déconnexion; s'il huponexitn'est bashpas défini , les enfants de ne seront pas SIGHUPped bashà la sortie / déconnexion;

Donc, en général, la fermeture / déconnexion d'une bashinstance de connexion interactive , sauf si l' huponexitoption est définie, ne fera pas du shell SIGHUP ses enfants, et la fermeture / déconnexion d'une bashinstance interactive sans connexion ne fera pas du shell SIGHUP ses enfants indépendamment;

Cela n'est cependant pas pertinent dans ce cas: l'utilisation kill -9 sleepsurvivra malgré tout, car la suppression de son processus parent ( bash) ne laissera aucune chance à ce dernier de faire quoi que ce soit à l'ancien (par exemple, si l' bashinstance actuelle était une bashinstance de connexion) . et l' huponexitoption a été définie, à SIGHUP it).

De plus, contrairement à d'autres signaux (comme un signal SIGHUP envoyé à bash), un signal SIGKILL n'est jamais propagé aux processus enfants d'un processus, il sleepn'est donc même pas tué;

nohupdémarre un processus insensible aux signaux SIGHUP, ce qui est différent; cela empêchera le processus de raccrocher à la réception d'un signal SIGHUP, qui dans ce cas pourrait être reçu par l' bashinstance de connexion interactive au cas où l' huponexitoption aurait été définie et le shell quitté; donc, techniquement, utiliser nohuppour démarrer un processus dans une bashinstance de connexion interactive avec l' huponexitoption unset empêchera le processus de raccrocher à la réception d'un signal SIGHUP, mais quitter / se déconnecter du shell ne le SIGHUP le fera pas indépendamment;

En général, cependant, lorsque cela nohupest nécessaire pour empêcher les signaux SIGHUP provenant du shell parent, il n'y a aucune raison de préférer la kill -9méthode on the parent à la méthode nohupon the child; au contraire, ce devrait être le contraire.

Tuer le parent à l'aide de la kill -9méthode ne laisse aucune chance au parent de sortir avec élégance, tandis que le démarrage de l'enfant à l'aide de la nohupméthode permet au parent d'être interrompu par d'autres signaux, tels que SIGHUP (pour donner un exemple qui a du sens dans le contexte d'un enfant a commencé à utiliser nohup), ce qui lui permet de sortir avec élégance.

kos
la source
En d'autres termes, si j'ai un script qui a été placé en arrière-plan, il sera toujours en cours d'exécution même si je tue le processus parent, par exemple mon shell n'est-ce pas? quelle serait une façon de tuer ce script?
Sergiy Kolodyazhnyy
@Serg Si vous avez le PID, il suffit de tuer le PID; si vous n'avez pas stocké le PID mais que vous pouvez identifier le processus par son nom, vous devez ps -e | grep processlister les processus avec le PID (ou mieux juste pgrep -x processsi vous êtes sûr de faire correspondre ce seul processus et non des choses non désirées); le problème est que lorsque vous tuez un processus avec kill -9ses enfants upstart, leur PPID d'origine est perdu et leur PPID change en PID parvenu, les rendant méconnaissables (AFAIK) mais pour leur nom ou PID
kos
@kos Dans quelle condition nohupn'empêchera-t-il pas un processus de raccrocher lors de la réception d'un signal SIGHUP du processus parent? J'essaie d'exécuter un processus en arrière-plan (dans un terminal shell PuTTY SSH) par nohup <command> <arg> &. Lorsque je me déconnecte en cliquant sur le Xbouton PuTTY , le processus d'arrière-plan se termine immédiatement. Lorsque je me déconnecte en tapant exitdans le terminal shell PuTTY SSH, le processus continue de s'exécuter en arrière-plan.
userpal
3

bashpar défaut n'envoie pas le signal HUP aux processus enfants lors de la fermeture . Plus en détail (merci @kos), il ne le fait jamais pour les shells sans connexion .

Vous pouvez configurer bash pour le faire pour les shells de connexion si vous définissez l'option huponexit. Dans un terminal, faites:

[romano:~] % bash -l

(ceci lance un nouveau shell "login")

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Maintenant, vérifiez le sleepprocessus:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... ne fonctionne pas: il a reçu le signal HUP et est sorti comme demandé.

Rmano
la source
@kos --- oui, vous avez raison , mais ... alors pourquoi si je sleep 1000 & ; exitles sleepsurvive? Notez que si je kill -HUPle sleepprocessus, il se terminera . Et même s'il est huponexitréglé, le sleepsurvit. Confus ... (je vais essayer de mieux comprendre et de modifier la réponse, sinon je vais le supprimer).
Rmano
2

Si sleeppeut survivre de cette façon, si cela signifie que je peux utiliser cette méthode au lieu de la nohupcommande?

kill -9ce n'est vraiment pas la voie à suivre. C'est comme tirer avec un pistolet sur le téléviseur pour l'éteindre. Outre la composante comique, il n'y a aucun avantage. Les processus ne peuvent pas attraper ou ignorer SIGKILL. Si vous ne donnez pas au processus une chance de terminer ce qu'il fait et de nettoyer, il peut laisser des fichiers corrompus (ou un autre état) et ne pourra pas redémarrer. kill -9est le dernier espoir, quand rien d'autre ne fonctionne.


Pourquoi le processus de sommeil peut survivre lorsque je me déconnecte et que le terminal est fermé. Dans mon esprit, tout sauf le démon et le programme nohup sera tué lors de la déconnexion.

Que se passe-t-il dans votre cas:

Le processus parent de sleepest le bashshell en cours d'exécution . Lorsque vous kill -9bash, le processus bash n'a pas la possibilité d'envoyer un SIGHUPà l'un de ses processus enfants, car SIGKILL(qui est envoyé par kill -9) n'est pas capturable par le processus. Le processus de mise en veille continue de s'exécuter. le sommeil est devenu un processus orphelin .

Le processus init (PID 1) fait un mécanisme appelé reparenting. Cela signifie que le processus init devient maintenant le parent de ce processus orphelin. init est une exception, les processus peuvent devenir son enfant car il collecte les processus qui ont perdu leur processus parent d'origine. Btw: Un démon (comme sshd) fait cela lorsqu'il "va en arrière-plan".

Si cela ne se produisait pas, le processus orphelin deviendrait plus tard (une fois terminé) un processus zombie. C'est ce qui se produit quand waitpid()n'est pas appelé (une responsabilité du processus parent qui ne peut pas être remplie lorsque ce processus a été tué). init appelle waitpid()dans un intervalle spécifique pour éviter les enfants zombies.

le chaos
la source
Le processus survit même avec des signaux polis comme TERMouHUP
heemayl
@heemayl HUP dépend de la configuration des coquilles: huponext. Et TERM attendra la fin du sommeil. Dans le cas de la commande OPs sleep, ce serait des milliers d'années =)
chaos
1

Le &démarre le processus en arrière-plan. Si vous tapez ps -ef, vous verrez que l'ID de processus parent (PPID) de votre sommeil est votre bash. Déconnectez-vous ensuite et reconnectez-vous. Le processus continuera de fonctionner après votre déconnexion. Après vous être connecté pour la deuxième fois, vous exécutez à ps -efnouveau. Vous verrez que maintenant le parent de votre processus de sommeil sera traité avec l'identifiant "1". C'est init, le parent de tous les processus.

personne
la source
0

L'utilisation &entraînera l'exécution du programme en arrière-plan. Pour voir le programme dans la bgcommande d' arrière-plan et le faire à nouveau fonctionner comme premier plan, exécutez fg.

Oui, il existe de nombreuses façons de continuer à exécuter le programme même après la sortie du terminal principal.

Aizuddin Zali
la source
Merci. la page de manuel de bash est un peu déroutante. Il a dit que: « Avant de quitter, un shell interactif renvoie le SIGHUP à tous les travaux, ou à l' arrêt. » Mais en fait, que la coquille envoyer SIGHUP aux forground emplois. les processus d'arrière-plan n'ont aucune chance de recevoir le signal SIGHUP (à moins de changer les options du shell 'huponexit')
tom_cat
@kos vous avez peut-être raison. Je tire la conclusion ci-dessus de cet article: stackoverflow.com/questions/4298741/… maintenant, je me fais plus confus.
tom_cat
@tom_cat Retour à ce nouveau, en pensant à deux fois: il n'y a tout simplement pas de cas où la coque peut sortir avec un processus de premier plan en cours d' exécution, il peut être SIGHUPped ou quelque chose, mais ce n'est pas sortie . Donc, c'est exact, cela ne s'applique qu'aux processus d'arrière-plan, car l'inverse n'aurait aucun sens. Cependant, d'après des recherches plus approfondies, n'oubliez pas que cela huponexitne fonctionne que sur les shells de connexion tels qu'un shell obtenu via ssh(et non, disons, dans un shell obtenu via gnome-terminal)
kos