Sistema y proceso de desove

14

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.

Bottswana
fuente
1
Es difícil proporcionar una solución sin tener el Server.pycó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 .
intelfx
Por cierto, el ExecStop=no es necesario. La acción predeterminada de systemd en stop es matar procesos. Es posible que desee consultar la documentación de la KillMode=directiva.
intelfx
1
Y, finalmente ... Si no hay un protocolo de preparación adecuado (uno de simpleo forking, en realidad), el último recurso sería Type=oneshot, RemainAfterExit=yesy KillMode=control-group.
intelfx
@intelfx Esencialmente, el script de Python inicia un servidor en una pantalla usando Subprocess.call. Es más complicado que eso porque el script recibe comandos de otros lugares que le dicen qué pantallas iniciar y cuáles no. Las pantallas disponibles también son dinámicas, por lo que no pueden ser servicios del sistema por derecho propio. Idealmente, no quiero que systemd trate estas pantallas como parte del servicio, pero actualmente quedan en el mismo grupo de procesos y mueren con el maestro si se reinicia.
Bottswana
Mi presentimiento es que systemd no "maneja" un proceso de control como ese (solo busca los PID al momento del inicio, no reconoce los posteriores ...): |
rogerdpack

Respuestas:

9

Logré solucionar esto simplemente configurando KillMode para procesar en lugar de control-group (predeterminado). Gracias a todos

Bottswana
fuente
Sin embargo, parece una solución más que una solución, vea las otras respuestas ... si hace esto y hace una "parada de systemctl", entonces no matará los procesos secundarios que todavía estarán ejecutando [?] fuera de la supervisión de systemctl?
rogerdpack
5

Tengo un script de Python que se bifurca cuando se inicia, y es responsable de iniciar un montón de otros procesos.

Lo que indica que lo estás haciendo mal. Más en esto en un momento.

cuando el script sale, los procesos secundarios quedan huérfanos y continúan ejecutándose.

Este no es el comportamiento correcto del demonio. Si el proceso "principal" - en este caso el niño que ha bifurcado, ya que ha especificadoType=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 rcscripts 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 un rcscript. 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 que ossec-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 opcionalagentlessdservicio, sin ninguna necesidad del horrendo mecanismo de "secuencia de comandos maestra" que se necesitaba con el Sistema 5 rc.

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 rcscript 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.

JdeBP
fuente
Agradezco los comentarios sobre esto. Si bien estoy de acuerdo con que los servicios de subconjuntos tienen sentido, se hizo en Python por una razón que no puedo analizar. Mi única solución es encontrar una manera de hacer que este método funcione. Gracias, sin embargo. Me encantaría hacerlo correctamente.
Bottswana
Los 'subservicios que lanza el script son solo servidores que se ejecutan en la pantalla gnu como un usuario específico. Estos servidores cambian mucho, algunos se agregan, otros se eliminan y esto se controla en otro lugar, por lo que realmente no pueden ser servicios reales en systemd, porque eso agrega mucha complejidad y no se puede administrar de forma centralizada. También el mismo script también se usa en servidores que no son systemd.
Bottswana
systemd tiene facilidades explícitas para permitir que se agreguen y eliminen servicios sin necesidad de acceso de root. El "también utilizado en servicios no systemd" es el único de los argumentos anteriores que no se puede solucionar agregando más systemd ... bueno, podría decirse que incluso podría serlo. :)
Charles Duffy el
0

Podrías dormir al padre y esperar a que systemd lo mate en el momento de la detención.

Craig Hicks
fuente