1
votes

Différence entre le démarrage d'un processus d'arrière-plan dans BASHRC et en ligne de commande

J'essaie de créer automatiquement un processus en arrière-plan.

   891    891    891 pts/2    Ss+    0:00 /bin/bash
   958    955    891 pts/2    Sl     0:00 program

Si je vérifie si le processus est en cours d'exécution et que je le lance lors de la connexion via ".bashrc", le programme démarre mais DIES lorsque je exit.

MAIS si je fais exactement la même commande sur la ligne de commande, le programme continue de fonctionner, en arrière-plan, lorsque je quitte.

Je ne trouve aucune différence dans environnement de programme entre un démarrage bashrc et un démarrage cli. (Le bashrc n'a presque rien dedans). Ma compréhension du programme dans les deux cas doit être traitée de la même manière.

Quelle est la différence, et comment puis-je empêcher qu'un «démon» démarré par bashrc soit tué lorsque le shell se termine.

PS: supprimer nohup ne fait aucune différence. et j'ai regardé le programme s'exécuter puis mourir d'une connexion séparée, lorsque la connexion de départ se termine.

Et avant que quelqu'un ne dise quoi que ce soit ... L'ajout de "désavouer" après avoir mis le programme en arrière-plan dans le bashrc ne l'a PAS corrigé !

MISE À JOUR: Si la connexion de connexion ssh est interrompue (fenêtre fermée ou connexion interrompue soudainement), le programme démarré dans le bashrc continue de s'exécuter, mais cela semble être dû au fait que le bash qui l'a démarré est également toujours en cours d'exécution (du moins pour le moment). L'arrière-plan n'est tué que si vous tapez "exit" pour le bash, ou si le bash est tué (même avec un signal non trappable 9!).

Le PPID du programme (désavoué par le shell) est 0 qui est son parent n'est pas le shell NI le processus d'initialisation! C'est le cas quel que soit le mode de démarrage.

MISE À JOUR 2 ... le programme d'arrière-plan a commencé à partir de bashrc ...

# ps -jA w
   PID   PGID    SID TTY      STAT   TIME COMMAND
   891    891    891 pts/2    Ss+    0:00 /bin/bash
   899    891    891 pts/2    Sl+    0:00 program

J'ai tué celui-là puis l'ai démarré à partir de la ligne de commande ...

nohup program > /tmp/program.log 2>&1 < /dev/null &
disown

Désormais, lorsque le shell existe, le programme ne se ferme pas. Il semble donc que la seule différence est que le PGID a changé.

Comment puis-je démarrer un processus dans un autre PGID?


3 commentaires

Pouvez-vous nous dire qui possède qui avec la commande pstree -gTt ?


Je ne peux pas reproduire ceci: sur ma machine, programme continue de fonctionner après la déconnexion même s'il est démarré à partir de .bashrc comme dans votre exemple


@Mathieu Le PPID du processus d'arrière-plan désavoué est 0. ce qui n'est ni init, ni bash. Peu importe comment bash est tué, quand il meurt, le processus d'arrière-plan meurt.


3 Réponses :


-1
votes

Chaque processus bash a un PPID (Parent PID)

Si vous exécutez ce qui suit à partir du terminal:

UID        PID  PPID  C STIME TTY          TIME CMD
user     16405 16404  0 Jun20 tty2     00:00:08 bash
user     18424 18386  0 16:17 tty1     00:00:00 tail -f /dev/null

Le PPID de ps -ef code> la sortie montre que le PPID est init (premier processus à démarrer):

UID        PID  PPID  C STIME TTY          TIME CMD
user     18424     1  0 16:17 tty1     00:00:00 tail -f /dev/null

Si vous exécutez la même commande depuis bashrc, le PPID est le processus bash:

XXX

Lors de l'exécution à partir du terminal, le processus se poursuivra jusqu'à l'arrêt de init.

Lors de l'exécution à partir de bashrc, le processus se poursuivra jusqu'à l'arrêt de bash.

p >


5 commentaires

D'accord, cela a du sens ... Je suppose ... Mais cela n'explique pas pourquoi il y a une différence, ou comment démarrer le processus d'arrière-plan dans le bashrc, pour ne plus avoir bash comme parent. PS: J'ai essayé de doubler le contexte du processus, mais peut-être que je l'ai mal fait. Je vais faire d'autres expériences.


Essayez de générer une autre instance Bash et de démarrer le processus à partir de là. Je dois cependant remettre en question la sagesse de démarrer des processus d'arrière-plan à partir de votre .bashrc - que se passe-t-il si vous démarrez plusieurs instances de Bash pour une utilisation interactive? Comment contrôlez-vous le processus? Quel service fournit-il qui ne pourrait pas être mieux fourni par d'autres moyens?


@tripleee note est juste sur l'argent que j'envisagerais d'utiliser crontab @reboot à la place


Il y a une vérification pour voir si le processus est déjà en cours d'exécution, et si tel est le cas, un autre n'est pas exécuté. Le démarrage du processus n'a jamais été un problème, le maintien du processus après la fermeture du shell est le problème.


Non ... après une enquête plus approfondie, le PPID n'est pas le problème. Le programme "disown" de bash semble mettre le processus parent à 0. Mais le processus continue d'appartenir aux shells PGID, mais seulement s'il est démarré à partir de bashrc.



0
votes

D'accord ... il semble que le problème soit en fait causé par l'environnement.

Le shell était exécuté dans un conteneur Docker. et il semble que Docker Exec soit celui qui termine tous les processus dans le même groupe de processus, pas le shell. Ou du moins, cela semble être le cas.

Cependant, je trouve toujours étrange qu'un programme basé sur ".bashrc" hérite du même groupe de processus que le shell parent, MAIS exactement la même commande d'arrière-plan de la ligne de commande obtient son propre groupe de processus séparé.

Une fois que j'ai découvert que c'était la cause, j'ai découvert que les groupes de processus étaient mentionnés dans la page de manuel BASH, en ce qui concerne le Backgrounding d'un processus, bien que cela ne fasse aucune mention de la différence de démarrage dans le ".bashrc" vs CLI.


0 commentaires

3
votes

Les groupes de processus sont nécessaires pour le contrôle des travaux, car un shell a besoin de quelque chose auquel envoyer des signaux de contrôle des travaux, par exemple lorsque vous tapez fg . POSIX.1-2017 états

Un processus d'interpréteur de commandes prenant en charge le contrôle des travaux peut allouer le terminal à différents travaux, ou groupes de processus , en plaçant les processus associés dans un seul groupe de processus et en associant ce groupe de processus au terminal

(les italiques sont à moi) Cela semble même assimiler les concepts de "groupe de processus" et de "travail", bien que la plupart des gens utilisent le terme "travail" pour les groupes de processus (et même les enfants dans le processus du shell. group) qui sont enregistrés dans la table de travail des shells (et peuvent être supprimés de cette table par le disown) intégré

Donc, si un shell ne Je ne veux pas démarrer une commande enfant (ou même un pipeline shell) sous le contrôle du travail, cela ne crée pas de nouveau groupe de processus (en appelant setpgrp())

Cela se produit par exemple lors de l'utilisation de la substitution de processus

blah=$(sleep 1000 | sleep 1000)

(essayez-le, et regardez la sortie de ps -jA w !) et, apparemment, au démarrage les commandes de .bashrc

nohup , par elles-mêmes, ne démarreront pas un nouveau groupe de processus, mais uniquement ignore SIGHUP puis exécute la commande

Linux (et d'autres systèmes d'exploitation lorsque vous installez quelque chose comme util-linux ) a une commande setsid qui sera faites ce que vous attendiez (mais n'avez pas obtenu) de nohup : La commande setsid créera un nouveau groupe de processus pour et en faire le chef de session d'une nouvelle session. Le PGID de ce nouveau groupe de processus sera inconnu de l'appelant ( bash dans ce cas) donc nous n'avons plus besoin d'utiliser nohup .

Alors, utilisez setsid au lieu de nohup et vous avez terminé (je ne vois que maintenant le commentaire de Mark Plotnick, qui est juste sur l'argent. Eh bien, j'espère que ma réponse clarifie également la raison pour laquelle setsid est la meilleure alternative dans ce cas)


1 commentaires

Merci Hans, cela fournit l'explication exacte ainsi que la solution dont j'avais besoin. J'ai marqué cela comme la solution préférée.