Como bifurcar um processo que não morre quando o shell sai?

31

Se eu executar o emacs a partir do shell:

$ emacs foo &

e depois mata aquela concha, o emacs morre.

Como posso executar um comando para que ele não morra quando o shell morrer?

Encontrei referências ao nohup, mas isso não parece ajudar:

$ nohup emacs foo &

ainda mata emacs quando a concha morre.

sligocki
fonte

Respostas:

13

Você não menciona se isso está sendo executado como um aplicativo X ou um aplicativo de console.

Se for um aplicativo de console, é claro que ele precisa ser fechado. Você se livrou de sua entrada / saída, mais tecnicamente o (pseudo) tty em que estava. É muito improvável que tenha sido isso que você quis dizer, então vamos supor que você esteja falando de um aplicativo X.

nohupdeve funcionar, não sei por que não é. Quando o shell é fechado, ele é enviado SIGHUPpara todos os processos em seu grupo de processos. nohup diz ao comando para ignorar SIGHUP.

Você também pode tentar setsid, que desconecta o processo do grupo de processos

alias emacs='setsid emacs'

Ou adicione disowndepois&

Rich Homolka
fonte
Ah, ótimos trabalhos. Desculpe por não ser claro. Sim, estou me referindo a aplicativos X que não são realmente executados no shell. Basicamente, quero iniciar o emacs (ou qualquer outro processo) a partir do shell, mas não o quero de forma alguma vinculado ao shell. Estou apenas começando por conveniência.
sligocki
41

O método mais confiável parece ser:

(setsid emacs &)

Isso usa ( &)para bifurcar em segundo plano e setsiddesanexar do controle tty.

Você pode colocar isso em uma função shell:

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

fork emacs

As possibilidades são:

  • O disowncomando embutido:

    emacs &
    disown $!
    

    &atua como separador de comandos e disownserá padronizado para o trabalho mais recente, portanto, isso pode ser reduzido para:

    emacs & disown
    
  • Duplo- fork():

    (emacs &)
    

    Os comandos entre parênteses ( )são executados em um processo de shell separado.

  • setsid, conforme sugerido por Rich, pode ser a melhor opção, porque desativa o TTY de controle do processo criando uma nova sessão :

    setsid emacs
    

    No entanto, também é um pouco imprevisível - será apenas um fork()pano de fundo se for o líder de um grupo de processos (o que não acontecerá se setsidfor usado em um shscript, por exemplo; em tais ocasiões, apenas se tornará resistente ao Ctrl- C.)

gravidade
fonte
Ótimo! tudo isso funciona para mim. É bom ter mais algumas ferramentas no meu arsenal.
sligocki
Hum ... (exec emacs)funcionaria?
Hello71
@ Olá: Não seria diferente de apenas (emacs). Se o subshell receber um único comando, isso execestará implícito, pelo menos no caso de bash. O mesmo se aplica a bash -c 'foo'versus bash -c 'exec foo'. (No entanto, nota que emacs em si podem ser destacados do terminal;.. Gvim, por exemplo, faz isso É melhor teste com um programa com o comportamento conhecido)
grawity
Ótimo para aprender sobre a técnica de garfo duplo; obrigado!
Dave Abrahams
Encontrei isso enquanto corria para corrigir um problema meu. O (setsid emacs &) funcionou para mim. Obrigado por uma resposta bem escrita.
Paulb 22/03
5

Verifique suas configurações de shell. Você também pode tentar a tela em vez de nohup.

Josh K
fonte
A tela permite que você volte ao processo mais tarde com screen -ro uso Ctrl-A Ctrl-Dde desconectá-lo antes de sair.
Broam 22/03/12
Este é um ponto muito bom. Eu precisava do oposto, ou seja, bifurcar um subshell e prosseguir com outras tarefas sem esperar pela conclusão, mas screen -d -m sh -c "{do stuff } exit"faz muito mais sentido.
Nemo