Normalmente no publico aquí, pero me estoy arrancando el pelo por este. Tengo un script de Python que se bifurca cuando se inicia, y es responsable de iniciar un montón de otros procesos. Este script solía lanzarse al inicio a través de sysvinit, pero recientemente me actualicé a Debian Jessie, así que lo he adaptado para que se inicie a través de systemd.
Desafortunadamente, me encuentro con un problema que no puedo resolver. Cuando inicia el script directamente en un shell de usuario, inicia sus procesos secundarios correctamente, y cuando el script sale, los procesos secundarios quedan huérfanos y continúan ejecutándose.
Cuando se inicia a través de systemd, si el proceso padre sale, todos los hijos también salen (¿Bueno, la pantalla que lanzan mueren y aparecen como muertos?)
Idealmente, necesito poder reiniciar el script principal sin eliminar todos los procesos secundarios, ¿hay algo que me falta?
¡Gracias!
[Unit]
Description=Server commander
After=network.target
[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid
ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
Editar: Probablemente sea relevante para mí señalar que el script Python es esencialmente un 'controlador' para sus procesos secundarios. Inicia y detiene servidores en pantallas de GNU según lo solicitado desde un servidor central. Normalmente siempre se está ejecutando, no genera servicios y sale. Sin embargo, hay casos en los que me gustaría poder volver a cargar el script sin eliminar los procesos secundarios, incluso si eso significa que los procesos quedan huérfanos a pid 1. De hecho, ni siquiera importaría si el script Python comenzara los procesos como un proceso padre, si eso es posible.
Una mejor explicación de cómo funciona:
- Systemd genera /Server.py
- Server.py se bifurca y escribe el archivo pid para Systemd
- Server.py genera procesos de servidor en la pantalla de GNU según sus instrucciones
- Server.py continúa ejecutándose para realizar cualquier reinicio solicitado desde el servidor
Cuando se inicia sin Systemd, Server.py se puede reiniciar y las pantallas gnu que inicia no se ven afectadas. Cuando se inicia con Systemd, cuando Server.py se cierra, en lugar de que los procesos de la pantalla se queden huérfanos a pid 1, se eliminan.
fuente
Server.py
código y una descripción de cómo se bifurcan los servicios lanzados (si se bifurcan). Sin embargo, en términos generales, este es un problema de falta de coincidencia del protocolo de preparación .ExecStop=
no es necesario. La acción predeterminada de systemd en stop es matar procesos. Es posible que desee consultar la documentación de laKillMode=
directiva.simple
oforking
, en realidad), el último recurso seríaType=oneshot
,RemainAfterExit=yes
yKillMode=control-group
.Respuestas:
Logré solucionar esto simplemente configurando KillMode para procesar en lugar de control-group (predeterminado). Gracias a todos
fuente
Lo que indica que lo estás haciendo mal. Más en esto en un momento.
Este no es el comportamiento correcto del demonio. Si el proceso "principal" - en este caso el niño que ha bifurcado, ya que ha especificado
Type=forking
, se cierra, systemd considera que el servicio se ha desactivado y finaliza cualquier otro proceso que aún se ejecutando (en el grupo de control) para ordenar .A veces, la conversión de
rc
scripts de System 5 a systemd no es sencilla, porque la forma correcta de hacer las cosas en systemd es bastante diferente. La forma correcta de hacer (por ejemplo) OpenVPN, OpenStack u OSSEC HIDS en systemd no es lo mismo que se haría con unrc
script. El hecho de que tenga una secuencia de comandos que se bifurca, luego genera una gran cantidad de procesos de nietos y luego sale esperando que esos nietos sigan ejecutándose indica que está perpetrando el mismo tipo de horror queossec-control
, aunque con dos niveles menos de bifurcación. Si se encuentra escribiendo una secuencia de comandos "maestra" que marca las banderas "habilitar" y ejecuta procesos secundarios para las partes "habilitadas" de su sistema, entonces está cometiendo el mismo error que el horrendoossec-control
.No se necesitan tales mecanismos locales con systemd. Que ya es un administrador de servicio. Según /unix//a/200365/5132 , la forma correcta de hacerlo en systemd es no tener un servicio que genere algún intento extraño y confuso de tener "sub-servicios". Es tener cada proceso hijo como un servicio systemd completo en su propio derecho. Luego, uno habilita y deshabilita, e inicia y detiene, las diversas partes del sistema utilizando los controles normales del sistema. Como puede ver en el caso OSSEC HIDS, una unidad de servicio de plantilla simple cubre casi todos los servicios (una excepción está en /ubuntu//a/624871/43344 ), lo que le permite a uno hacer cosas como
systemctl enable [email protected]
habilitar un servicio opcionalagentlessd
servicio, sin ninguna necesidad del horrendo mecanismo de "secuencia de comandos maestra" que se necesitaba con el Sistema 5rc
.Hay muchos casos, tal vez no tan extremos como OSSEC HIDS, en los que es necesario repensarlo. MTS como exim y sendmail son dos de estos. Uno podría haber tenido un solo
rc
script que genera un corredor de cola, un demonio de envío SMTP y un demonio de retransmisión SMTP, con un montón de variables de shell ad hoc en un archivo de configuración para controlar exactamente cuáles se ejecutan. Pero la forma correcta de hacer esto con systemd es tener tres unidades de servicio adecuadas (dos de las cuales tienen unidades de socket asociadas ) y ningún elemento ad hoc, solo los mecanismos regulares del administrador de servicios.fuente
Podrías dormir al padre y esperar a que systemd lo mate en el momento de la detención.
fuente