ver segundo procesos proceso plano mandar lanzar enviar ejecutar comandos linux shell telnet job-control

segundo - procesos en background y foreground linux



¿Linux mata los procesos en segundo plano si cerramos el terminal desde el que se inició? (4)

¿Quién debería matar empleos?

Normalmente, los trabajos en primer plano y en segundo plano son eliminados por SIGHUP enviados por el kernel o el shell en diferentes circunstancias.

¿Cuándo el kernel envía SIGHUP ?

Kernel envía SIGHUP al proceso de control :

  • para terminal real (hardware): cuando se detecta una desconexión en un controlador de terminal, p. ej., en la línea de módem;
  • para pseudoterminal (pty): cuando el último descriptor que hace referencia al lado maestro de pty está cerrado, por ejemplo, cuando cierra la ventana de terminal.

Kernel envía SIGHUP a otros grupos de proceso:

  • al grupo de proceso de primer plano , cuando el proceso de control termina;
  • al grupo de proceso huérfano , cuando queda huérfano y ha dejado de miembros.

El proceso de control es el líder de la sesión que estableció la conexión con el terminal de control.

Típicamente, el proceso de control es tu shell. Así que para resumir:

  • el kernel envía SIGHUP al shell cuando se desconecta / cierra real o pseudoterminal;
  • el kernel envía SIGHUP al grupo de proceso en primer plano cuando el shell termina;
  • el kernel envía SIGHUP al grupo de procesos huérfanos si contiene procesos detenidos.

Tenga en cuenta que el kernel no envía SIGHUP al grupo de procesos en segundo plano si no contiene procesos detenidos.

¿Cuándo bash envía SIGHUP ?

Bash envía SIGHUP a todos los trabajos (primer plano y fondo):

  • cuando recibe SIGHUP y es un shell interactivo (y el soporte de control de trabajos está habilitado en tiempo de compilación);
  • cuando sale, es un shell de inicio de sesión interactivo y se huponexit opción huponexit (y se habilita el soporte de control de trabajos en tiempo de compilación).

Ver más detalles here .

Notas:

  • bash no envía SIGHUP a trabajos eliminados de la lista de trabajos usando disown ;
  • los procesos comenzaron a usar nohup ignorar SIGHUP .

Más detalles here .

¿Qué pasa con otras conchas?

Por lo general, las conchas se propagan SIGHUP . Generar SIGHUP en la salida normal es menos común.

Telnet o SSH

Bajo telnet o SSH, debe ocurrir lo siguiente cuando se cierra la conexión (por ejemplo, cuando cierra la ventana de telnet en la PC):

  1. el cliente es asesinado
  2. el servidor detecta que la conexión del cliente está cerrada;
  3. el servidor cierra el lado maestro de pty;
  4. el kernel detecta que la pty maestra está cerrada y envía SIGHUP a bash ;
  5. bash recibe SIGHUP , envía SIGHUP a todos los trabajos y termina;
  6. Cada trabajo recibe SIGHUP y termina.

Problema

Puedo reproducir su problema usando bash y telnetd desde el servidor SSH de busybox o dropbear : a veces , el trabajo en segundo plano no recibe SIGHUP (y no finaliza) cuando se cierra la conexión del cliente.

Parece que se produce una condición de carrera cuando el servidor ( telnetd o telnetd ) cierra el lado maestro de pty:

  1. normalmente, bash recibe SIGHUP e inmediatamente mata los trabajos en segundo plano (como se espera) y termina;
  2. pero a veces, bash detecta EOF en el lado esclavo de pty antes de manejar SIGHUP .

Cuando bash detecta EOF , de forma predeterminada termina inmediatamente sin enviar SIGHUP . ¡Y el trabajo de fondo sigue en marcha!

Solución

Es posible configurar bash para enviar SIGHUP en la salida normal (incluido EOF ) también:

  • Asegúrese de que bash se inicia como shell de inicio de sesión . El huponexit here solo para shells de inicio de sesión, AFAIK.

    El shell de inicio de sesión se habilita mediante la opción -l o el guión argv[0] en argv[0] . Puede configurar telnetd para ejecutar /bin/bash -l o mejor /bin/login que invoca /bin/sh en el modo shell de inicio de sesión.

    P.ej:

    telnetd -l /bin/login

  • Habilitar la opción huponexit .

    P.ej:

    shopt -s huponexit

    Escriba esto en la sesión de bash cada vez o agréguelo a .bashrc o /etc/profile .

¿Por qué ocurre la carrera?

bash desbloquea las señales solo cuando es seguro y las bloquea cuando alguna sección de código no puede ser interrumpida de manera segura por un manejador de señales.

Dichas secciones críticas invocan puntos de interrupción de vez en cuando, y si se recibe una señal cuando se ejecuta una sección crítica, su controlador se retrasa hasta que se produce el siguiente punto de interrupción o se abandona la sección crítica.

Puede comenzar a excavar desde quit.h en el código fuente.

Por lo tanto, parece que en nuestro caso, a veces, bash recibe SIGHUP cuando está en una sección crítica. SIGHUP ejecución del controlador SIGHUP se retrasa, y bash lee EOF y termina antes de salir de la sección crítica o llamar al siguiente punto de interrupción.

Referencia

  • Sección "Control de trabajos" en el manual oficial de Glibc.
  • Capítulo 34 "Grupos de procesos, sesiones y control de trabajos" del libro "La Interfaz de programación de Linux".

Tengo un sistema integrado, en el que hago telnet y luego ejecuto una aplicación en segundo plano:

./app_name &

Ahora si cierro mi terminal y hago telnet desde otra terminal y si lo compruebo, puedo ver que este proceso todavía se está ejecutando.

Para comprobarlo he escrito un pequeño programa:

#include<stdio.h> main() { while(1); }

Ejecuté este programa en mi computadora local de Linux en segundo plano y cerré la terminal.

Ahora, cuando verifiqué este proceso desde otra terminal, descubrí que este proceso también fue cancelado.

Mi pregunta es:

  • ¿Por qué comportamiento indefinido para el mismo tipo de proceso?
  • ¿De cuál es dependiente?
  • ¿Depende de la versión de Linux?

AFAIK en ambos casos el proceso debe ser matado. Para evitar esto, debes emitir un nohup como el siguiente:

> nohup ./my_app &

De esta manera su proceso continuará ejecutándose. Probablemente la parte de telnet se deba a un error similar a este:

https://bugzilla.redhat.com/show_bug.cgi?id=89653


Cuando cierras el terminal, el shell envía SIGHUP a todos los procesos en segundo plano, y eso los mata. Esto se puede suprimir de varias maneras, sobre todo:

nohup

Cuando ejecutas un programa con nohup , captura SIGHUP y redirige la salida del programa.

$ nohup app &

desconocer

disown le dice a shell que no envíe SIGHUP

$ app & $ disown

¿Depende de la versión de linux?

Depende de tu concha. Lo anterior se aplica al menos para bash .


Para comprender completamente lo que está sucediendo, debe ingresar un poco a los unix internos de unix .

Cuando está ejecutando un comando como este

./app_name &

El nombre de app_name se envía al grupo de proceso en segundo plano. Puedes consultar los grupos de proceso de unix here

Cuando cierra bash con salida normal, se dispara la señal de SIGHUP a todos sus trabajos. Alguna información sobre el control de trabajo de unix está here .

Para mantener su aplicación en ejecución cuando salga de bash , debe hacer que su aplicación sea inmune a la señal de nohup con la utilidad nohup .

nohup - ejecuta un comando inmune a los cuelgues, con salida a un no-tty

Y finalmente así es como necesitas hacerlo.

nohup app_name & 2> /dev/null;