¿Por qué mi proceso aún se está ejecutando después de cerrar sesión?

10

Después de iniciar sesión ssh, escribo este comando bash:

sleep 50000000000000 &

Luego, kill -9el sleepproceso padre del proceso (es decir, bash). Entonces la ventana de terminal se desconecta simultáneamente.

Cuando vuelvo a iniciar sesión, encuentro que el sleepproceso todavía está vivo.

Pregunta : ¿Por qué puede sleepsobrevivir el proceso cuando salgo y el terminal está cerrado? En mi opinión, todo, excepto los demonios y los nohupprogramas, se eliminarán durante el cierre de sesión. Si sleeppuede sobrevivir de esta manera, ¿significa que puedo usar este método en lugar del nohupcomando?

gato
fuente
3
&bifurcará el proceso en segundo plano (como daemon) y seguirá ejecutándose aunque haya cerrado la sesión.
Aizuddin Zali

Respuestas:

6

Tl; dr:

¿Por qué puede sleepsobrevivir el proceso cuando salgo y el terminal está cerrado? En mi opinión, todo, excepto los demonios y los nohupprogramas, se eliminarán durante el cierre de sesión. Si sleeppuede sobrevivir de esta manera, ¿significa que puedo usar este método en lugar del nohupcomando?

A menos que la bashinstancia generada sshtenga la huponexitopción establecida, ningún proceso terminará por ningún medio al salir / cerrar sesión, y cuando la huponexitopción está configurada, el uso kill -9en el shell no es una buena alternativa al uso nohupen los procesos secundarios del shell; nohupen los procesos secundarios del shell aún los protegerá de SIGHUPs que no provienen del shell, e incluso cuando eso no nohupes importante, todavía es preferible porque permite que el shell finalice con gracia.


En bashhay una opción llamada huponexit, que si se establece hará bashSIGHUP sus hijos al salir / cerrar sesión;

En las bash instancias interactivas sin inicio de sesión , como en una bashinstancia generada por gnome-terminal, esta opción se ignora; ya huponexitsea que esté activado o desactivado, bashlos niños nunca serán VISTOS bashal salir;

En instancias de inicio de sesión interactivas bash, como en una bashinstancia generada por ssh, esta opción no se ignora (sin embargo, no está activada de forma predeterminada); si huponexitestá configurado, bashlos hijos de SIGHUP se verán bashal salir / cerrar sesión; si no huponexitestá configurado, bashlos hijos de 'SIGHUP' no se verán bashal salir / cerrar sesión;

Por lo tanto, en general, salir / cerrar sesión de una bashinstancia de inicio de sesión interactiva , a menos que se establezca la huponexitopción, no hará que el shell SIGHUP sea secundario, y salir / cerrar sesión de una bashinstancia interactiva sin inicio de sesión no hará que el shell SIGHUP sea secundario sin importar;

Sin embargo, esto es irrelevante en este caso: el uso kill -9 sleepsobrevivirá independientemente, porque matar su proceso padre ( bash) no dejará una oportunidad para que el último haga nada al primero (es decir, por ejemplo, si la bashinstancia actual era una bashinstancia de inicio de sesión y huponexitse configuró la opción, SIGHUP it).

Además de esto, a diferencia de otras señales (como una señal SIGHUP enviada a bash), una señal SIGKILL nunca se propaga a los procesos secundarios de un proceso, por sleeplo tanto, ni siquiera se elimina;

nohupinicia un proceso inmune a las señales SIGHUP, que es algo diferente; evitará que el proceso se cuelgue al recibir una señal SIGHUP, que en este caso podría ser recibida por la bashinstancia de inicio de sesión interactiva en caso de que huponexitse estableciera la opción y se cerrara el shell; por lo que, técnicamente, usar nohuppara iniciar un proceso en una bashinstancia de inicio de sesión interactiva con la huponexitopción deshabilitada evitará que el proceso se cuelgue al recibir una señal SIGHUP, pero salir / cerrar sesión del shell no lo SIGHUP independientemente;

Sin embargo, en general, cuando nohupse necesita para evitar que las señales SIGHUP provengan del shell principal, no hay razón para preferir el kill -9método principal al método nohupsecundario; en cambio, debería ser lo contrario.

Matar al padre usando el kill -9método no deja una oportunidad para que el padre salga con gracia, mientras que al comenzar el niño usando el nohupmétodo permite que el padre sea terminado por otras señales, como SIGHUP (para hacer un ejemplo que tenga sentido en el contexto de un niño comenzó a usar nohup), lo que le permite salir con gracia.

kos
fuente
En otras palabras, si tengo un script que se colocó en segundo plano, todavía se ejecutará incluso si elimino el proceso principal, por ejemplo, mi shell ¿verdad? ¿Cuál sería una forma de matar ese guión?
Sergiy Kolodyazhnyy
@Serg Si tiene el PID, simplemente elimine el PID; si no almacenó el PID pero puede identificar el proceso por su nombre, ps -e | grep processdebe enumerar el proceso junto con el PID (o mejor solo pgrep -x processsi está seguro de que coincide con ese proceso único y no con las cosas no desechadas); el problema es que cuando eliminas un proceso en el que kill -9sus hijos son propiedad upstart, por lo tanto, su PPID original se pierde y su PPID cambia al PID inicial, lo que los hace irreconocibles (AFAIK) pero por su nombre o PID
kos
@kos ¿En qué condición nohupno podrá evitar que un proceso cuelgue al recibir una señal SIGHUP del proceso principal? Estoy tratando de ejecutar un proceso en segundo plano (en un terminal de shell PuTTY SSH) por nohup <command> <arg> &. Cuando cierre sesión haciendo clic en el Xbotón PuTTY , el proceso en segundo plano finalizará de inmediato. Cuando cierre sesión escribiendo exiten el terminal shell PuTTY SSH, el proceso continuará ejecutándose en segundo plano.
userpal
3

bashde manera predeterminada , no envía la señal HUP a los procesos secundarios al salir . Más en detalle (gracias @kos), nunca lo hace para shells sin inicio de sesión .

Puede configurar bash para hacerlo para shells de inicio de sesión si establece la opción huponexit. En una terminal, haz:

[romano:~] % bash -l

(Esto inicia un nuevo shell de "inicio de sesión")

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Ahora verifique el sleepproceso:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... no se está ejecutando: recibió la señal HUP y salió como se solicitó.

Rmano
fuente
@kos --- sí, tienes razón, pero ... ¿por qué si yo sleep 1000 & ; exitlos sleepsobrevive? Tenga en cuenta que si kill -HUPel sleepproceso saldrá . E incluso si se huponexitestablece, el sleepsobrevive. Confundido ... (Intentaré comprender mejor y modificar la respuesta, de lo contrario lo eliminaré).
Rmano
2

Si sleeppuede sobrevivir de esta manera, ¿significa que puedo usar este método en lugar del nohupcomando?

kill -9realmente no es el camino por el que uno debería ir. Es como disparar con una pistola al televisor para apagarlo. Además del componente cómico no hay ventaja. Los procesos no pueden atrapar o ignorar SIGKILL. Si no le da al proceso la oportunidad de terminar lo que está haciendo y limpiar, puede dejar archivos corruptos (u otro estado) y no podrá comenzar de nuevo. kill -9Es la última esperanza, cuando nada más funciona.


¿Por qué el proceso de suspensión puede sobrevivir cuando salgo y el terminal está cerrado? En mi opinión, todo, excepto el programa daemon y nohup, se eliminará al cerrar sesión.

Qué sucede en tu caso:

El proceso padre de sleepes el bashshell actualmente en ejecución . Cuando realiza kill -9ese bash, el proceso de bash no tiene la posibilidad de enviar un correo electrónico SIGHUPa ninguno de sus procesos secundarios, porque SIGKILL(el cual es enviado por kill -9) no es detectable por el proceso. El proceso de suspensión continúa ejecutándose. dormir ahora se convirtió en un proceso huérfano .

El proceso init (PID 1) hace un mecanismo llamado reparenting. Eso significa que el proceso init ahora se convierte en el padre de ese proceso huérfano. init es una excepción, los procesos pueden convertirse en su hijo, ya que recopila procesos que perdieron su proceso padre original. Por cierto: un demonio (como sshd) hace eso cuando "va en segundo plano".

Si eso no ocurriera, el proceso huérfano se convertiría más tarde (cuando haya terminado) en un proceso zombie. Esto es lo que sucede cuando waitpid()no se llama (una responsabilidad del proceso padre que no se puede cumplir cuando se cancela ese proceso). init llama waitpid()en un intervalo específico para evitar niños zombies.

caos
fuente
El proceso está sobreviviendo incluso con señales educadas como TERMoHUP
heemayl
@heemayl HUP depende de la configuración de conchas: huponext. Y TERM esperará hasta que termine el sueño. En el caso del comando de suspensión de los OP, serían miles de años =)
caos
1

El &comienza el proceso en segundo plano. Si escribe ps -ef, verá que la ID de proceso principal (PPID) de su sueño es su bash. Luego cierre sesión y vuelva a iniciar sesión. El proceso seguirá ejecutándose después de cerrar sesión. Después de iniciar sesión por segunda vez, ps -efvuelve a ejecutar . Verá que ahora el padre de su proceso de suspensión será procesado con la identificación "1". Es init, el padre de todos los procesos.

nadie
fuente
0

El uso &hará que el programa se ejecute como fondo. Para ver el programa en segundo plano, use el bgcomando, y para que vuelva a ejecutarse como primer plano, ejecute fg.

Sí, hay muchas maneras de mantener el programa ejecutándose incluso cuando se salga del terminal principal.

Aizuddin Zali
fuente
Gracias. La página de manual de bash es un poco confusa. Decía que: "Antes de salir, un shell interactivo reenvía el SIGHUP a todos los trabajos, en ejecución o detenidos". PERO, de hecho, el shell solo envía SIGHUP a los trabajos forground . los procesos en segundo plano no tienen posibilidad de recibir la señal SIGHUP (a menos que cambie las opciones de shell 'huponexit')
tom_cat
@kos tal vez tengas razón. Saco la conclusión anterior de esta publicación: stackoverflow.com/questions/4298741/... ahora, me confundo más.
tom_cat
@tom_cat Volviendo a esto de nuevo, pensándolo dos veces: simplemente no hay caso en el que el shell pueda salir con un proceso en primer plano en ejecución, puede ser SIGHUPped o algo así, pero eso no existe . Así que eso es correcto, se aplica solo a los procesos en segundo plano, porque lo contrario no tendría sentido. Sin embargo, a partir de investigaciones posteriores, tenga en cuenta que huponexitsolo funciona en shells de inicio de sesión, como un shell obtenido a través de ssh(y no, por ejemplo, en un shell obtenido a través de gnome-terminal)
kos