Quelle est la différence entre exécuter un programme en tant que démon et le mettre en arrière-plan avec '&'?

46

Quelles sont les différences pratiques d'un point de vue administrateur système lors du déploiement de services sur un système Unix?

utilisateur1561108
la source

Réponses:

31

La méthode traditionnelle de démonisation est la suivante:

fork()
setsid()
close(0) /* and /dev/null as fd 0, 1 and 2 */
close(1)
close(2)
fork()

Cela garantit que le processus ne fait plus partie du même groupe de processus que le terminal et ne sera donc pas tué en même temps. La redirection IO consiste à faire en sorte que la sortie n'apparaisse pas sur le terminal.

Dennis Kaarsemaker
la source
5
donc, si un terminal qui génère un processus en arrière-plan (&) est fermé, le processus en arrière-plan sera également terminé?
user1561108
9
Le processus reçoit SIGHUP lorsque le terminal se ferme, le gestionnaire par défaut pour ce signal est de mettre fin au processus.
Dennis Kaarsemaker
12
S'il vous plaît ajouter l' &explication de la partie à votre réponse. Cela semble être incomplet .. si vous cochez la question initiale.
MTK
1
C'est parce que faire fonctionner les choses en arrière-plan avec et ne fait pas que le processus fasse quelque chose de spécial :)
Dennis Kaarsemaker
34

Pour un démon, vous voulez un processus qui n’a aucun lien avec quoi que ce soit. Au minimum, vous voulez qu'il soit dans sa propre session, qu'il ne soit pas attaché à un terminal, qu'aucun descripteur de fichier hérité du parent ne soit ouvert à rien, qu'aucun parent ne s'occupe de vous (autre qu'init) répertoire dans /afin de ne pas empêcher un umount ...

Pour vous détacher d'un terminal, vous créez une nouvelle session. Toutefois, pour créer une session, vous ne devez pas être un responsable de groupe (ou de session). Il est donc préférable de créer un nouveau processus. En supposant que le parent quitte, cela signifie également que le processus n'aura plus de parent et sera adopté par init. Ensuite, fermez tous les descripteurs de fichiers possibles chdir("/")( vous ne pouvez pas fermer le répertoire de travail en cours pour libérer cette ressource comme pour les descripteurs de fichiers, la création /des répertoires de travail actuels n’empêchant pas au moins le démontage des répertoires).

Ce processus étant un leader de session, il risque de devenir le processus de contrôle de ce terminal s'il ouvre un terminal. Forking une deuxième fois assure que cela n'arrive pas.

À l’autre extrémité, &, dans les shells interactifs, crée et crée un nouveau groupe de processus (afin de ne pas figurer dans le groupe de processus de premier plan du terminal), et dans les shells non interactifs, lance un processus et ignore le contenu de SIGINT. Il ne se détache pas du terminal, ne ferme pas les descripteurs de fichiers (même si certains shells rouvriront stdin /dev/null) ...

Stéphane Chazelas
la source
Quelle est l'utilisation de chdir ("/")? fermer le descripteur de fichier?
Timothy Leung
@ TimothyLeung, voir edit.
Stéphane Chazelas
8

La différence entre exécuter un programme / processus en tant que démon et le transférer en arrière-plan à l'aide de l'esperluette est essentiellement liée à la propriété.

Le plus souvent, le processus parent d'un démon est le processus init (le tout premier processus à démarrer sur un système Unix), le démon étant un enfant de ce processus, il n'est pas sous votre contrôle direct en tant qu'utilisateur non privilégié. . De l’autre côté, mettre un programme / processus en arrière-plan signifie que vous pouvez à tout moment le rappeler au premier plan et / ou le supprimer.

Odaym
la source
1
Également pour répondre à l'aspect technique ci-dessus du détachement d'un processus plutôt que de le conserver en tant qu'enfant du terminal, vous pouvez essayer de
lancer
7

Avec command &Votre processus sera tué par un signal SIGHUP lorsque le parent mourra.

Les administrateurs système ont toutefois accès à certaines solutions de contournement.

Sur un système bash, vous pouvez utiliser:

(trap '' HUP; command) &

Cela ouvre un sous-shell, intercepte le HUPsignal avec un gestionnaire vide et l'esperluette / le forque.

La sortie peut toujours être redirigée vers le mauvais tty. Ou se perdre.
Vous pouvez corriger cela avec &>command.out, 1>output.outou2>errors.out

Vous pouvez également avoir accès, sur la plupart des systèmes, à la nohupcommande.
nohupsimplifie grandement ce processus. C'est assez standard, mais j'ai trouvé de nombreuses distributions ARM intégrées busybox le manquer. Vous venez d'écrire:

nohup command &

..et tu as fini. La sortie est redirigée, IIRC, vers nohup.out, mais ce nom de fichier peut être modifié avec une option.

ZJR
la source
2
Juste pour noter qu'avec ZSH, vous pouvez découpler un command &shell ultérieur avec disownlequel fonctionne ensuite comme post-nohup.
math