Comment puis-je bifurquer un processus qui ne meurt pas lorsque le shell se termine?

31

Si je lance emacs depuis le shell:

$ emacs foo &

puis tuez cet obus, emacs meurt.

Comment puis-je exécuter une commande pour qu'elle ne meure pas lorsque le shell meurt?

J'ai trouvé des références à nohup, mais cela ne semble pas aider:

$ nohup emacs foo &

tue toujours les emacs lorsque la coquille meurt.

sligocki
la source

Réponses:

13

Vous ne mentionnez pas si cela fonctionne comme une application X ou une application console.

S'il s'agit d'une application console, elle doit bien sûr être fermée. Vous vous êtes débarrassé de ses entrées / sorties, plus techniquement du (pseudo) tty sur lequel il était. Il est très peu probable que ce soit ce que vous vouliez dire, supposons donc que vous parlez d'une application X.

nohupdevrait fonctionner, je ne sais pas pourquoi ce n'est pas le cas. Lorsque le shell se ferme, il envoie SIGHUPà tous les processus de son groupe de processus. nohup indique à la commande d'ignorer SIGHUP.

Vous pouvez également essayer setsid, qui déconnecte le processus du groupe de processus

alias emacs='setsid emacs'

Ou ajoutez disownaprès&

Rich Homolka
la source
Ah, de grandes œuvres de setid. Désolé de ne pas être clair. Oui, je fais référence à des applications X qui ne s'exécutent pas réellement dans le shell. Fondamentalement, je veux démarrer emacs (ou tout autre processus) à partir du shell, mais je ne veux pas qu'il soit lié au shell. Je commence juste par là pour plus de commodité.
sligocki
41

La méthode la plus fiable semble être:

(setsid emacs &)

Cela permet ( &)de bifurquer vers l'arrière-plan et setsidde se détacher du terminal de contrôle.

Vous pouvez mettre cela dans une fonction shell:

fork() { (setsid "$@" &); }

fork emacs

Les possibilités sont:

  • La disowncommande intégrée:

    emacs &
    disown $!
    

    &agit comme séparateur de commandes et disownsera par défaut le travail le plus récent, donc cela peut être raccourci à:

    emacs & disown
    
  • Double- fork():

    (emacs &)
    

    Les commandes entre parenthèses ( )sont exécutées dans un processus shell distinct.

  • setsid, comme suggéré par Rich, pourrait être le meilleur choix, car il désactive le contrôle ATS du processus en créant une nouvelle session :

    setsid emacs
    

    Cependant, il est également un peu imprévisible - il ne sera mis fork()en arrière-plan que s'il est le leader d'un groupe de processus (ce qui ne se produira pas s'il setsidest utilisé dans un shscript, par exemple; dans de telles occasions, il deviendra simplement résistant à Ctrl- C.)

grawity
la source
Génial! tout cela fonctionne pour moi. Ravi d'avoir plus d'outils dans mon arsenal.
sligocki
Hm ... ça (exec emacs)marcherait?
Hello71
@ Bonjour: Ce ne serait pas différent de juste (emacs). Si le sous-shell reçoit une seule commande, le execest implicite, au moins en cas de bash. La même chose s'applique à bash -c 'foo'versus bash -c 'exec foo'. (Cependant, notez qu'emacs lui - même peut se détacher du terminal; gvim, par exemple, le fait. Il vaut mieux tester avec un programme avec un comportement connu.)
grawity
Idéal pour apprendre la technique de la double fourche; Merci!
Dave Abrahams
J'ai trouvé cela pendant la pêche à la traîne pour résoudre mon propre problème. Le (setsid emacs &) a fonctionné pour moi. Merci pour une réponse bien écrite.
Paulb
5

Vérifiez vos paramètres de shell. Vous pouvez également essayer l' écran au lieu de nohup.

Josh K
la source
L'écran vous permet de reprendre le processus plus tard avec screen -rsi vous l'utilisez Ctrl-A Ctrl-Dpour le déconnecter avant de vous déconnecter.
Broam
C'est un très bon point. J'avais besoin du contraire, c'est-à-dire bifurquer un sous-shell et procéder à d'autres tâches sans attendre sa fin, mais screen -d -m sh -c "{do stuff } exit"c'est beaucoup plus logique.
Nemo