Cómo detener todos los procesos secundarios generados por un servicio

Cómo detener todos los procesos secundarios generados por un servicio

Tengo un servicio ejecutándose en Ubuntu con la siguiente configuración:

#/etc/init/my_service.conf

start on (local-filesystems and net-device-up IFACE=eth1)

respawn

exec python -u /opt/XYZ/my_prog.py 2>&1 \
                 | logger -t my_prog.py

Al detener el servicio con sudo service my_service stop, el proceso de Python no finaliza. Matar el proceso principal killtampoco mata el proceso de Python.

¿Cómo detengo completamente el servicio (es decir, se eliminan todos los procesos secundarios)? Idealmente, me gustaría no modificar el archivo de configuración anterior.

Respuesta1

Idealmente, me gustaría no modificar el archivo de configuración anterior.

¡Difícil! Es la cosa justa que hacer.

Debe cambiar execa scripty dejar de ejecutar ese programa Python en un subproceso bifurcado como parte de una canalización. Esta respuesta de ServerFaultexplica cómo hacer esto en un script de shell integrado. Haría solo un cambio en el script que aparece allí, en la última línea:

exec python -u /opt/XYZ/my_prog.py 2>&1

Después de todo, no hay realmente una buena razón para no registrar también el error estándar.

Los giros cada vez más complejos para hacer frente a la bifurcación, desde expect daemonel cambio hasta el systemd, pasan por alto el punto de que lo correcto es hacerevitar que el demonio se bifurque. Si algo bueno puede surgir del alboroto actual es la confirmación continua de que lo que IBM escribió y recomendó en 1995 ha sido correcto durante todos estos años.

Acostúmbrate a la idea decarga de cadenademonios. Hay muchos conjuntos de herramientas que simplifican estas cosas. Acostúmbrate también a la idea de no utilizar scripts de shell. Hay muchos conjuntos de herramientas diseñados específicamente para este trabajo, que eliminan los gastos generales de los shells (que es una buena idea conocida en el mundo Ubuntu).

Por ejemplo: los comandos de shell en la respuesta de ServerFault se pueden reemplazar con un script que useexeclineLas herramientas de Laurent Bercotque están diseñados para poder hacer esto mismo sin subcapas y FIFO desvinculados:

#!/command/execlineb -PW
pipeline -w {
    logger -t my_prog.py
} 
fdmove -c 2 1 
python -u /opt/XYZ/my_prog.py

que luego simplemente

exec /foo/this_execlineb_script

Conmi noshconjunto de herramientas, de manera similar sería un script que contendría:

#!/usr/local/bin/nosh
pipe 
fdmove -c 2 1 
python -u /opt/XYZ/my_prog.py | logger -t my_prog.py

O alternativamente, se podría tener esta estrofa directamente en la definición del trabajo Upstart (usando un truco para evitar los metacaracteres del shell para que Upstart no genere un shell):

exec /usr/local/bin/exec pipe --separator SPLIT fdmove -c 2 1 python -u /opt/XYZ/my_prog.py SPLIT logger -t my_prog.py

Otras lecturas

Respuesta2

En GNU/Linux, normalmente, no hay forma de detener un servicio y todos los procesos secundarios que generó, porque los procesos secundarios pueden cambiar su PPID (ID de proceso principal). La única manera de saberlo seríarastroel sistema llama para generar procesos a medida que se crean y mantiene una lista de estos procesos.

El sistema de inicio de Ubuntu upstartno hace esto. Entonces la respuesta a tu pregunta eses imposible-- en Ubuntu -- sin:

  1. Modificando ese guión;
  2. Saber exactamente qué ID de proceso genera ese proceso;
  3. Realizar un seguimiento de esos ID de proceso manualmente;
  4. Matarlos individualmente.

Esta es la razón por la que deberías ejecutar una distribución de Linux que ejecutesistemad. Como puedes ver, systemdrealiza un seguimiento de todos los procesos secundariosy puede matar a cada uno de ellos con una sola orden. Así es la administración del sistema GNU/Linuxdebiera ser, pero debido a que systemd es tan nuevo y debido a que "no se inventó aquí" (es decir, Canonical no lo inventó), Ubuntu no quiere usarlo.

Respuesta3

Te has saltado elesperarestrofa. Ellibro de cocina advenedizoespecifica:

Advertencia

Esta estrofa es sumamente importante: ¡lee esta sección con atención!

Upstart realizará un seguimiento del ID del proceso que cree que pertenece a un trabajo. Si un trabajo ha especificado la estrofa de instancia, Upstart rastreará los PID para cada instancia única de ese trabajo.

Si no especifica la estrofa esperada, Upstart rastreará el ciclo de vida del primer PID que ejecuta en las estrofas exec o script. Sin embargo, la mayoría de los servicios de Unix se "daimonizarán", lo que significa que crearán un nuevo proceso (usando fork(2)) que es hijo del proceso inicial. A menudo, los servicios se bifurcan para garantizar que no tengan asociación alguna con el proceso inicial. (Tenga en cuenta que ningún servicio se bifurcará más de dos veces inicialmente, ya que no hay ningún beneficio adicional al hacerlo).

En este caso, Upstart debe tener una forma de rastrearlo, por lo que puede usar expect fork o expect daemon que permite a Upstart usar ptrace(2) para "contar bifurcaciones".

Para permitir que Upstart determine el ID del proceso final para un trabajo, necesita saber cuántas veces ese proceso llamará a fork(2). El propio Upstart no puede saber la respuesta a esta pregunta, ya que una vez que se ejecuta un demonio, podría bifurcar una serie de procesos "trabajadores" que a su vez podrían bifurcarse cualquier número de veces. No se puede esperar que Upstart sepa qué PID es el "maestro" en este caso, considerando que no sabe si se crearán procesos de trabajo, y mucho menos cuántas veces o cuántas veces el proceso se bifurcará inicialmente. Como tal, es necesario decirle a Upstart qué PID es el PID "maestro" o padre. Esto se logra usando la estrofa expect.

Necesita esto porque la tubería |que está utilizando está creando procesos secundarios. Puedes encontrar en el libro.Programación avanzada de Linuxuna breve introducción a eso, donde se afirma que:

Por ejemplo, este comando de shell hace que el shell produzca dos procesos secundarios, uno paraesy uno paramenos:

 $ ls | less

Lo que no sé es si esto implica una o dos bifurcaciones, por lo que experimentaría modificando la línea.reapareceren su código con cualquiera

 expect fork
 respawn

o

 expect daemon
 respawn

No creo que esto se pueda lograr.soloconsistemad, aunque mi logo muestra claramente que soy fanático desistemad.

información relacionada