¿Por qué “el proceso no debe bifurcarse” para servicios de tipo simple en systemd?
Quiero escribir mis propios systemd
archivos de unidad para administrar comandos 1 de ejecución realmente larga (en el orden de horas). Mientras mira el artículo de ArchWiki sobre systemd , dice lo siguiente con respecto a la elección de un tipo de inicio:
Type=simple
(predeterminado): systemd considera que el servicio se inicia inmediatamente. El proceso no debe bifurcarse . No utilice este tipo si es necesario solicitar otros servicios en este servicio, a menos que esté activado por socket.
¿Por qué el proceso no debe bifurcarse en absoluto? ¿Se refiere a la bifurcación al estilo del proceso de invocación del demonio (bifurcaciones principales, luego salidas), o cualquier tipo de bifurcación?
1 No quiero tmux / screen porque quiero una forma más elegante de comprobar el estado y reiniciar el servicio sin tener que recurrir a tmux send-keys
.
Respuestas
El servicio puede llamar a la llamada al fork
sistema. Systemd no lo evitará, ni siquiera notará si lo hace. Esta oración se refiere específicamente a la práctica de bifurcar al comienzo de un demonio para aislar el demonio de su proceso padre. “El proceso no debe bifurcarse [y salir del padre mientras se ejecuta el servicio en un proceso hijo]”.
La página de manual explica esto de manera más detallada y con una redacción que no conduce a esta confusión en particular.
Muchos programas destinados a ser utilizados como demonios tienen un modo (a menudo el modo predeterminado) en el que cuando se inician, se aíslan de su padre. El demonio se inicia, llama fork()
y sale el padre. El proceso hijo llama setsid()
para que se ejecute en su propio grupo de procesos y sesión, y ejecute el servicio. El propósito es que si el demonio se invoca desde una línea de comandos de shell, el demonio no recibirá ninguna señal del kernel o del shell, incluso si algo le sucede al terminal, como el cierre del terminal (en cuyo caso el shell envía SIGHUP a todos los grupos de procesos que conoce). Esto también hace que init adopte el proceso de mantenimiento, que lo cosechará cuando salga, evitando un zombi si el demonio fue iniciado por algo que no wait()
lo haría (esto no sucedería si el demonio fuera iniciado por un shell ).
Cuando un daemon se inicia mediante un proceso de supervisión como systemd, la bifurcación es contraproducente. Se supone que el proceso de monitoreo reinicia el servicio si falla, por lo que necesita saber si el servicio sale, y eso es difícil si el servicio no es un hijo directo del proceso de monitoreo. Se supone que el proceso de monitoreo no morirá nunca y no tiene una terminal de control, por lo que no hay preocupaciones sobre señales no deseadas o cosecha. Por lo tanto, no hay ninguna razón para que el proceso de servicio no sea un elemento secundario del monitor, y hay una buena razón para que lo sea.
Ignora esta página wiki de Arch.
Ha hecho las cosas bastante mal con respecto al Type
entorno. simple
Además, esto no se limita a sus descripciones . Lo que dice también forking
está mal.
Las recomendaciones correctas para este tipo de cosas han existido durante décadas más de lo que systemd ha existido, y se remontan al menos a principios de la década de 1990. Como señalé enhttps://unix.stackexchange.com/a/476608/5132, en el documento de systemd hay una versión reciente de las recomendaciones para demonios que repite en gran medida lo que los usuarios de daemontools, IBM, la gente que usa inittab
y ... bueno ... he estado diciendo durante décadas. (Ya era una respuesta frecuente cuando la escribí como tal en 2001).
Repetir:
Si su programa tiene algún mecanismo de "demonización", que en particular bifurca a un niño y sale del proceso principal, apáguelo y no lo use . Gracias a daemontools et al. donde esto ha sido un requisito durante mucho tiempo, muchos programas han aumentado la capacidad de no tener tales mecanismos en los últimos 20 años, y otros simplemente no están predeterminados para "demonizar" en primer lugar, por lo que pueden usarse en sus modos de funcionamiento predeterminados.
Los subsistemas de gestión de servicios ya lanzan procesos de servicio en el contexto de damon . Estos procesos no necesitan "demonizar". (De hecho, es una falacia en muchos sistemas operativos modernos pensar que los programas incluso pueden "demonizar" desde un contexto de sesión de inicio de sesión, que es de lo que realmente se trata la "demonización"). Ya tienen los valores del entorno y los descriptores de archivos abiertos, apropiado al contexto del demonio, y las diversas cosas que se hacen mediante la "demonización" de hecho frustran algunas de las cosas convencionales que los gerentes de servicio hacen regularmente con los demonios (por ejemplo, capturar sus salidas / errores estándar en un registro).
Preferiblemente Type=simple
, con apertura temprana de sockets (donde la administración de servicios abre sockets de servidor y los pasa como descriptores de archivo ya abiertos al programa de servicio), o Type=notify
.
Type=simple
trata el servicio como listo (para que los servicios solicitados puedan iniciarse / detenerse) tan pronto como se inicia el proceso de servicio, con la apertura temprana del socket empleando la semántica de conexión del socket para retrasar a los clientes del servicio, en los puntos en los que intentan conectarse a los servidores para servicio, hasta que los servidores estén realmente listos.Type=notify
tiene la desventaja de ser peculiar de systemd y de Linux (junto con los problemas de no ser funcional a partir de procesos de corta duración, como la generación de un shellsystemd-notify
, y de emplear el análisis de formularios legibles por humanos en formularios legibles por máquinas en un proceso privilegiado, donde Los problemas del analizador ya han ocurrido en el pasado) pero tiene la ventaja de proporcionar un control más preciso (desde el punto de vista del programa de servicio) de cuándo se considera que el servicio está realmente listo. También permite cierta personalización de la salida de estado.
Los programas de servicio, de ambos tipos, pueden bifurcarse. Es bifurcar y luego salir del proceso original que es el problema.
(Cabe señalar que esto es un problema tanto para ejecutar programas desde shells como para ejecutar programas desde administradores de servicios, ya que los usuarios ven que los programas terminan y provocan otro indicador de shell casi de inmediato. , acerca de ejecutar programas desde el shell que se bifurcan y salen del padre, en ¿Por qué a veces cuando ejecuto un programa en la terminal, no se ejecuta en la terminal? )
Type=oneshot
Probablemente no sea lo que desea en este caso particular, ya que el servicio se considera listo solo cuando todo el programa de servicio se ha completado. Tiene sus usos, pero por lo que parece, no se aplican a usted.
Nunca use Type=forking
. Debería ser un último recurso de desesperación, ya que casi ningún programa habla realmente del protocolo . Están haciendo otra cosa , que de hecho no es este protocolo, que no es correctamente interoperable con este protocolo y, de hecho, no indica la preparación.
Otras lecturas
- Jonathan de Boyne Pollard (2001). Errores a evitar al diseñar programas demonio Unix . Respuestas frecuentes.
- Jonathan de Boyne Pollard (2015). Realmente no necesitas demonizar. De Verdad. . La Casa del Horror systemd.
- Jonathan de Boyne Pollard (2015). Problemas de protocolo de preparación con demonios de Unix . Respuestas frecuentes.
- https://unix.stackexchange.com/a/401611/5132