En el pasado, cuando era joven y Unix era lo nuevo, crear un proceso que no se eliminara cuando se desconectaba era un desafío. Usamos el comando nohup para proteger nuestros procesos persistentes de la señal HUP . Si no tuviéramos cuidado, nuestros procesos se matarían cuando cerráramos la sesión, o incluso cerraríamos el shell desde el que los iniciamos.
Avance rápido hasta hoy y me sorprende que el valor predeterminado parezca ser exactamente lo contrario. En los sistemas Ubuntu y Red Hat, encuentro que puedo poner casi cualquier proceso en segundo plano, eliminar el shell principal, cerrar sesión, cualquier cosa y simplemente continuar. Veo el mismo comportamiento con los scripts de Bash, los scripts de Python y los programas en C. Obtengo el mismo comportamiento de las sesiones xterm o ssh.
Por ejemplo, en una ventana xterm o ssh, escriba:
while [ 1 ]; do date; sleep 10; done > /tmp/out &Ahora desde otra ventana ejecuta
tail -f /tmp/outMírelo imprimir la fecha cada 10 segundos, luego cierre el shell principal original con Ctrl-D. Sigue corriendo. Cierra la sesión y vuelve a iniciarla. Todavía en ejecución.
Envíale una señal HUP , muere instantáneamente.
Puedo exhibir el mismo comportamiento con un script Python o un programa C. Dormir o no, no importa. Por ejemplo, este feo programa en C se comporta igual:
#include <stdio.h> void main() { while(1) { printf("*\n"); fflush(stdout); int i, j, k = 0; for(i=0; i < 10000; i++) { for(j=0; j < 100000; j++) { k += i * j; } } } } Esto es completamente contrario a los caminos de mi juventud. ¿Supongo que simplemente no me di cuenta cuando cambió? ¿Algún historiador sabe cuándo sucedió esto? ¿Se sigue utilizando HUP para este propósito?
Si de hecho este es el estado actual de las cosas, mi pregunta es: ¿Cómo puedo hacer que un proceso muera cuando el usuario cierra la sesión o se desconecta?
Tengo un truco que consiste en observar si el ppid (pid principal) cambia, pero seguramente hay algo más elegante que eso.
Creo que estás buscando la opción de shell huponexit . Puede configurar esto fácilmente con
$ shopt -s huponexitAlgunos detalles de la página de manual de bash:
El shell sale de forma predeterminada al recibir un SIGHUP. Antes de salir, un shell interactivo vuelve a enviar el SIGHUP a todos los trabajos, en ejecución o detenidos. Los trabajos detenidos se envían SIGCONT para asegurarse de que reciben SIGHUP. Para evitar que el shell envíe la señal a un trabajo en particular, debe eliminarse de la tabla de trabajos con el disown incorporado (ver COMANDOS INTERNOS DEL SHELL a continuación) o marcarlo para que no reciba SIGHUP usando disown -h.
Si la opción de shell huponexit se ha configurado con shopt, bash envía un SIGHUP a todos los trabajos cuando sale un shell de inicio de sesión interactivo.
Todavía recibo un SIGHUP. Una forma sencilla de probar:
#!/usr/bin/env sh echo "$$" trap "echo HUPPED $$ > /tmp/willithup" HUP sleep 1000Luego cierre el emulador de terminal. Ahora volvamos a tu pregunta:
Mírelo imprimir la fecha cada 10 segundos, luego cierre el shell principal original con Ctrl-D. Sigue corriendo. Cierra la sesión y vuelve a iniciarla. Todavía en ejecución.
El proceso no obtiene un HUP cuando muere su padre. Obtiene un HUP cuando pierde la conexión con el terminal de control o cuando se le envía explícitamente un HUP. Esto sucede, por ejemplo, cuando cierra la sesión de SSH.
Si no tuviéramos cuidado, nuestros procesos se matarían cuando cerráramos la sesión, o incluso cerraríamos el shell desde el que los iniciamos.
Para el segundo: el propio shell puede enviar un HUP a todos sus hijos cuando sale. Sin embargo, bash, por ejemplo, tiene huponexit establecido en falso de forma predeterminada. Esto bien puede ser lo que ha cambiado. Tenga en cuenta que, independientemente de la opción huponexit, cuando recibe un HUP, el shell también envía un HUP a todos sus elementos secundarios.
En palabras de Stevens:
Una sesión puede tener un solo terminal de control. Este suele ser el dispositivo terminal (en el caso de un inicio de sesión de terminal) o dispositivo pseudo terminal (en el caso de un inicio de sesión de red) en el que iniciamos sesión.
Si la interfaz del terminal detecta una desconexión del módem (o de la red), la señal de colgar se envía al proceso de control (el líder de la sesión).
Para aclarar aún más, el shell no envía el HUP inicial . Lo envía el conductor de la terminal. Luego, el caparazón lo "reenvía" a los niños. De hecho, un HUP enviado por el controlador de la terminal puede "en cascada". De TLPI:
Cuando un proceso de control pierde su conexión terminal, el núcleo le envía una señal SIGHUP para informarle de este hecho . (También se envía una señal SIGCONT para garantizar que el proceso se reinicie en caso de que haya sido detenido previamente por una señal). Normalmente, esto puede ocurrir en dos circunstancias:
- Cuando el controlador de terminal detecta una "desconexión", lo que indica una pérdida de señal en un módem o línea de terminal.
- Cuando se cierra una ventana de terminal en una estación de trabajo. Esto ocurre porque el último descriptor de archivo abierto para el lado maestro del pseudoterminal asociado con la ventana del terminal está cerrado.