Diferencia entre nohup, disown y &

578

¿Cuáles son las diferencias entre

$ nohup foo

y

$ foo &

y

$ foo & 
$ disown
lesmana
fuente
50
Espera, ¿puedes negarlo sin especificar un PID? ¡Excelente!
ripper234
34
También hay lo foo &!que debería ser igual a rechazarlo desde el principio.
user4514
26
Bash no es compatible con & !.
Jonas Kongslund
20
foo & disownpara repudiar de inmediato.
ctrl-alt-delor
99
Me encantaría ver una mención de setsid, y cómo se relaciona con disownynohup
YoungFrog el

Respuestas:

557

Primero veamos qué sucede si un programa se inicia desde un shell interactivo (conectado a una terminal) sin &(y sin ninguna redirección). Así que supongamos que acabas de escribir foo:

  • Se foocrea el proceso en ejecución .
  • El proceso hereda stdin, stdout y stderr del shell. Por lo tanto, también está conectado al mismo terminal.
  • Si el shell recibe un SIGHUP, también envía un SIGHUPal proceso (que normalmente hace que el proceso finalice).
  • De lo contrario, el shell espera (se bloquea) hasta que finaliza el proceso.

Ahora, veamos qué sucede si pones el proceso en segundo plano, es decir, escribe foo &:

  • Se foocrea el proceso en ejecución .
  • El proceso hereda stdout / stderr del shell (por lo que aún escribe en el terminal).
  • El proceso en principio también hereda stdin, pero tan pronto como intenta leer desde stdin, se detiene.
  • Se incluye en la lista de trabajos en segundo plano que gestiona el shell, lo que significa especialmente:
    • Está en la lista jobsy se puede acceder usando %n(donde nestá el número de trabajo).
    • Se puede convertir en un trabajo en primer plano utilizando fg, en cuyo caso continúa como si no lo hubiera utilizado &(y si se detuvo debido a intentar leer desde la entrada estándar, ahora puede proceder a leer desde el terminal).
    • Si el shell recibió un SIGHUP, también envía un SIGHUPal proceso. Dependiendo del shell y posiblemente de las opciones establecidas para el shell, al terminar el shell también enviará un mensaje SIGHUPal proceso.

Ahora disownelimina el trabajo de la lista de trabajos del shell, por lo que todos los subpuntos anteriores ya no se aplican (incluido el proceso enviado SIGHUPpor el shell). Sin embargo, tenga en cuenta que todavía está conectado al terminal, por lo que si el terminal se destruye (lo que puede suceder si fue una pty, como las creadas por xtermo ssh, y el programa de control finaliza, cerrando el xterm o finalizando la conexión SSH ) , el programa fallará tan pronto como intente leer desde la entrada estándar o escribir en la salida estándar.

Lo que nohupsí, por otro lado, es separar efectivamente el proceso del terminal:

  • Cierra la entrada estándar (el programa no podrá leer ninguna entrada, incluso si se ejecuta en primer plano. No se detiene, pero recibirá un código de error o EOF).
  • Redirige la salida estándar y el error estándar al archivo nohup.out, por lo que el programa no fallará al escribir en la salida estándar si el terminal falla, por lo que no se pierde lo que escriba el proceso.
  • Impide que el proceso reciba un SIGHUP(de ahí el nombre).

Tenga en cuenta que nohupno no eliminar el proceso de control de trabajo de la cáscara y también no lo pone en segundo plano (pero desde un plano nohupde trabajo es más o menos inútil, que había por lo general lo puso en el fondo usando &). Por ejemplo, a diferencia de disown, el shell aún le dirá cuándo se ha completado el trabajo de nohup (a menos que el shell finalice antes, por supuesto).

Entonces para resumir:

  • & pone el trabajo en segundo plano, es decir, lo bloquea al intentar leer la entrada y hace que el shell no espere a que se complete.
  • disownelimina el proceso del control de trabajo del shell, pero aún lo deja conectado al terminal. Uno de los resultados es que el shell no lo enviará a SIGHUP. Obviamente, solo se puede aplicar a trabajos en segundo plano, porque no se puede ingresar cuando se está ejecutando un trabajo en primer plano.
  • nohupdesconecta el proceso del terminal, redirige su salida nohup.outy lo protege SIGHUP. Uno de los efectos (el nombre) es que el proceso no recibirá ninguno enviado SIGHUP. Es completamente independiente del control del trabajo y, en principio, podría usarse también para trabajos en primer plano (aunque eso no es muy útil).
celtschk
fuente
8
+1 gracias. ¿Qué sucede cuando se usa disown, nohup y & together?
Tim
15
Si usa los tres juntos, el proceso se ejecuta en segundo plano, se elimina del control de trabajo del shell y se desconecta efectivamente del terminal.
celtschk
1
¿Cuál es la diferencia entre disown %1y disown -h %1? ¿El segundo se mantendrá como un trabajo normal (pero ignora la señal HUP) hasta la salida del terminal?
schemacs
44
Quizás valga la pena incluir (foo&)subshell
jiggunjer
169

El uso &hace que el programa se ejecute en segundo plano, por lo que obtendrá un nuevo indicador de shell en lugar de bloquearlo hasta que finalice el programa. nohupy en disowngran medida no están relacionados; suprimen las señales SIGHUP (colgar) para que el programa no se elimine automáticamente cuando se cierra el terminal de control. nohuphace esto cuando el trabajo comienza por primera vez. Si no hace nohupun trabajo cuando comienza, puede usarlo disownpara modificar un trabajo en ejecución; sin argumentos, modifica el trabajo actual, que es el que acaba de establecerse

Michael Mrozek
fuente
10
Diferencia menor entre nohup y disown: el comando disown lo eliminará de su lista de trabajos; No, no lo hará.
Shawn J. Goff el
191
nohupy disownse puede decir que ambos suprimen SIGHUP, pero de diferentes maneras. nohuphace que el programa ignore la señal inicialmente (el programa puede cambiar esto). nohuptambién trata de hacer arreglos para que el programa no tenga un terminal de control, de modo que SIGHUPel núcleo no lo envíe cuando el terminal esté cerrado. disownes puramente interno al caparazón; hace que el shell no se envíe SIGHUPcuando termina.
Gilles
27
@Gilles, tu comentario merece una respuesta en sí mismo.
lesmana
55
Solo una aclaración sobre el comentario de @ ShawnJ.Goff sobre la disowneliminación del trabajo de la lista de trabajos. Si no especifica una opción, la elimina de la lista de trabajos. Sin embargo , si especifica la -hopción, cada especificación de trabajo no se elimina de la tabla. En cambio, hace que SIGHUPno se envíe al trabajo si el shell recibe un SIGHUP.
Tacotuesday
44
Solo para aclarar, el uso &no le da un terminal, se separa stdindel proceso y hace que se ejecute en segundo plano, pero ambos stdouty stderrtodavía está conectado al tty actual. Esto significa que puede obtener texto de diferentes programas mezclados, lo que puede ser bastante molesto si lo hace gimp &y obtiene muchos errores GTK + al intentar usar ese tty para otra cosa.
Frank
8

Aquí está mi experiencia tratando de ejecutar soffice en segundo plano, siguiendo un comando que no termina (por ejemplo tail). Para este ejemplo lo usaré sleep 100.

Y

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

I veo soffice logs / pulsando Ctrl- Cparadas soffice

nohup .. &

#!/bin/bash
nohup /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

No veo registros de soffice / presionando Ctrl- Csoffice se detiene

y repudiar

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard & disown
sleep 100

I veo soffice logs / pulsando Ctrl- Cparadas soffice

setsid .. &

#!/bin/bash
setsid /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Me veo soffice troncos / pulsando Ctrl- Csoffice no se detiene

Para ahorrar espacio:
nohup setsid ..: no muestra logs / soffice NO PARA sobre Ctrl-C
nohup con & disownal final: no muestra logs / soffice detiene en Ctrl-C

Marinos An
fuente
2
Si bien aprecio el esfuerzo de mencionar setsid y mostrar lo que sucede en esa situación específica, me gustaría ver una respuesta más completa. En particular, la diferencia y las similitudes de cada solución, tanto visibles (lo que sucede cuando se cierra el shell o el terminal, a dónde va la salida, ...) como invisibles (cómo se hacen las cosas bajo el capó y sus implicaciones). La respuesta aceptada es una buena base para eso.
YoungFrog
1
@YoungFrog ¡Estaré de acuerdo en esto!
Marinos An
Para mí, con nohup ⟨command⟩ & disownel proceso creado no se detiene Ctrl+C.
k.stm
@ k.stm ¿Lo intentaste soffice? sofficeEl comando parece tener algo diferente. Así que consideré agregarlo aquí como una excepción de la regla. por ejemplo, cuando se utiliza: nohup .. &presionar Ctrl-cnormalmente no hace que el comando se detenga, pero sofficesí lo hace. Espero hasta que alguien pise esto y explique por qué sucede esto con soffice :)
Marinos An
@MarinosAn Sí, lo hice. Corrí nohup soffice &y presioné Ctrl+C. No pasó nada, como se esperaba.
k.stm