¿Cómo bifurco un proceso que no muere cuando sale el shell?

31

Si ejecuto emacs desde el shell:

$ emacs foo &

y luego mata ese caparazón, emacs muere.

¿Cómo puedo ejecutar un comando para que no muera cuando muera el shell?

Encontré referencias a nohup, pero eso no parece ayudar:

$ nohup emacs foo &

Todavía mata a Emacs cuando Shell muere.

sligocki
fuente

Respuestas:

13

No menciona si esto se ejecuta como una aplicación X o una aplicación de consola.

Si es como una aplicación de consola, por supuesto, debe cerrarse. Se deshizo de su entrada / salida, más técnicamente el (pseudo) tty en el que estaba. Es muy poco probable que esto sea lo que quisiste decir, así que supongamos que estás hablando de una aplicación X.

nohupdebería funcionar, no estoy seguro de por qué no lo es. Cuando el shell se cierra, envía SIGHUPa todos los procesos en su grupo de procesos. nohup le dice al comando que ignore SIGHUP.

También puede probar setsid, que desconecta el proceso del grupo de procesos

alias emacs='setsid emacs'

O agregue disowndespués&

Rich Homolka
fuente
Ah, un gran setid funciona. Perdón por no ser claro. Sí, me refiero a las aplicaciones X que en realidad no se ejecutan en el shell. Básicamente, quiero iniciar emacs (o cualquier otro proceso) desde el shell, pero no quiero que esté vinculado de ninguna manera al shell. Solo estoy comenzando allí por conveniencia.
sligocki
41

El método más confiable parece ser:

(setsid emacs &)

Esto se utiliza ( &)para bifurcar a fondo y setsidpara separarse del control tty.

Puede poner esto en una función de shell:

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

fork emacs

Las posibilidades son:

  • El disowncomando incorporado:

    emacs &
    disown $!
    

    &actúa como un separador de comandos y disown, por defecto, se convertirá en el trabajo más reciente, por lo que esto se puede acortar a:

    emacs & disown
    
  • Doble- fork():

    (emacs &)
    

    Los comandos dentro de paréntesis ( )se ejecutan en un proceso de shell separado.

  • setsid, tal como lo sugiere Rich, podría ser la mejor opción, ya que desarma el TTY de control del proceso al crear una nueva sesión :

    setsid emacs
    

    Sin embargo, también es un poco impredecible: solo pasará fork()a segundo plano si es el líder de un grupo de procesos (lo que no sucederá si setsidse usa en un shscript, por ejemplo; en tales ocasiones simplemente se volverá resistente a Ctrl- DO.)

Gravedad
fuente
¡Excelente! Todo esto funciona para mí. Es bueno tener algunas herramientas más en mi arsenal.
sligocki
Hm ... ¿ (exec emacs)funcionaría?
Hola71
@Hola: No sería diferente de solo (emacs). Si el subshell recibe un comando único, el execestá implícito, al menos en el caso de bash. Lo mismo se aplica a bash -c 'foo'versus bash -c 'exec foo'. (Sin embargo, nota que emacs pueden separar desde el terminal;.. Gvim, por ejemplo, ¿esto Es mejor prueba con un programa con el comportamiento conocido)
grawity
Genial para aprender la técnica del doble tenedor; ¡Gracias!
Dave Abrahams
Encontré esto mientras pescaba para solucionar un problema propio. El (setsid emacs &) funcionó para mí. Gracias por una respuesta bien escrita.
Paulb
5

Comprueba tu configuración de shell. También puedes probar la pantalla en lugar de nohup.

Josh K
fuente
Screen le permite volver al proceso más adelante screen -rsi lo Ctrl-A Ctrl-Ddesconecta antes de cerrar la sesión.
Broam
Este es un muy buen punto. Necesitaba lo contrario, es decir, bifurcar un subshell y continuar con otras tareas sin esperar a que se complete, pero screen -d -m sh -c "{do stuff } exit"tiene mucho más sentido.
Nemo