Procesar descendientes


20

Estoy tratando de construir un contenedor de procesos. El contenedor activará otros programas. Por ejemplo, un script bash que inicia la ejecución de tareas en segundo plano con el uso '&'.

La característica importante que busco es esta: cuando mato el contenedor, todo lo que se generó debajo de él debe ser asesinado. No solo los niños directos, sino también sus descendientes.

Cuando comencé este proyecto, creí erróneamente que cuando mataste un proceso, sus hijos también fueron matados automáticamente. He buscado consejo de personas que tenían la misma idea incorrecta. Si bien es posible captar una señal y transmitir la muerte a los niños, eso no es lo que estoy buscando aquí.

Creo lo que quiero lograr, porque cuando cierras un xterm, todo lo que se ejecuta dentro de él se mata a menos que se haya prohibido. Esto incluye procesos huérfanos. Eso es lo que estoy buscando recrear.

Tengo una idea de que lo que estoy buscando implica sesiones de Unix.

Si hubiera una forma confiable de identificar a todos los descendientes de un proceso, sería útil poder enviarles también señales arbitrarias. por ejemplo, SIGUSR1.


Bueno, matar el proceso padre envía SIGHUPa sus procesos hijos directos. El controlador predeterminado de la señal de colgar cancela la ejecución del proceso, por lo que la ruta predeterminada es matar a todos los descendientes. Lea más sobre procesos y grupos de procesos.
alex

Cerrar el xterm mata todo lo generado en el xterm porque el TTY se destruye. Si puede encontrar una manera de crear un tty que los procesos secundarios puedan usar, puede destruir el TTY y lograr lo mismo. Cualquier proceso que no cerró ese TTY (nohup y amigos) obtendrá un SIGHUP.
Patrick

Respuestas:


23

Si envía una señal a un proceso, ese proceso se anula. Me pregunto cómo comenzó el rumor de que matar un proceso también mata a otros procesos, parece particularmente contra-intuitivo.

Sin embargo, hay formas de matar más de un proceso. Pero no enviará una señal a un proceso. Puede matar a todo un grupo de procesos enviando una señal a -1234 donde 1234 es el PGID (ID del grupo de procesos), que es el PID del líder del grupo de procesos. Cuando ejecuta una canalización , toda la canalización comienza como un grupo de procesos (las aplicaciones pueden cambiar esto llamando setpgido setpgrp).

Cuando inicia procesos en segundo plano ( foo &), están en su propio grupo de procesos. Los grupos de procesos se usan para administrar el acceso al terminal; normalmente solo el grupo de procesos en primer plano tiene acceso al terminal. Los trabajos en segundo plano permanecen en la misma sesión , pero no existe la posibilidad de matar una sesión completa o incluso enumerar los grupos de procesos o procesos en una sesión, por lo que eso no ayuda mucho.

Cuando cierra una terminal, el núcleo envía la señal SIGHUPa todos los procesos que la tienen como terminal de control . Estos procesos forman una sesión , pero no todas las sesiones tienen un terminal de control. Por lo tanto, para su proyecto, una posibilidad es iniciar todos los procesos en su propio terminal, creado por script , pantalla , etc. Elimine el proceso del emulador de terminal para eliminar los procesos contenidos (suponiendo que no se hayan separado setsid).

Puede proporcionar más aislamiento ejecutando los procesos como su propio usuario, que no hace nada más. Entonces es fácil matar todos los procesos: ejecutar kill(la llamada al sistema o la utilidad ) como ese usuario y usar -1 como argumento PID para matar, lo que significa "todos los procesos de ese usuario".

Puede proporcionar aún más aislamiento, pero con una configuración considerablemente mayor ejecutando los procesos contenidos en un contenedor real .


Si programa sus propios procesos, puede utilizar algo como: prctl(PR_SET_PDEATHSIG, SIGHUP);más información: man7.org/linux/man-pages/man2/prctl.2.html
Alexis Wilke

Gilles, mencionas esto: "Cuando cierras una terminal, el núcleo envía la señal SIGHUP a todos los procesos que la tienen como terminal de control". A partir de esto , supongo que el terminal envía SIGHUP al líder de la sesión (shell) que lo reenvía a todos los grupos de procesos dentro de la sesión. ¿Cuál de los dos estaría en lo correcto?
iruvar

4

Dentro del script principal, atrape la señal de muerte y haga que mate a todos los niños. Por ejemplo,

#!/bin/bash
# kill the parent and children together
trap "kill 0" EXIT
# create all the children
for n in $(seq 1 100)
do
    ( echo "begin $n"; sleep 60; echo "end $n" ) &
done
# wait for the children to complete
wait

2

Una forma confiable de identificar a todos los descendientes de un proceso es usar el comando pstree <pid>donde pid es su identificación de proceso principal.

Lea la página de manual pstree aquí .

Para señalar a todos los miembros de un grupo de procesos: killpg(<pgrp>, <sig>);
donde pgrp es el número del grupo de procesos y sig es la señal.

Para esperar a los niños en un grupo de proceso específico: waitpid(-<pgrp>, &status, ...);

Una alternativa a lo que está haciendo es ejecutar su contenedor de procesos en un nuevo shell bash. Cree el nuevo bash shell con el comando bashy luego ejecute sus procesos. Cuando desee que finalicen todos los procesos, salga del shell con el comando exit.


Creo que killpg me permitirá hacer lo que necesito hacer. Gracias.
Craig Turner

1

Utilizar

unshare -fp --kill-child -- yourprogram

Si matas unshare, todos los procesos secundarios (que yourprogrampueden haber generado) serán eliminados.

Esto ahora es posible con util-linux 2.32; Implementé esto aguas arriba . Requiere espacios de nombres de usuario (opción de configuración del núcleo CONFIG_USER_NS=y) o privilegios de root. Ver también aquí .


0

El comando rkill del paquete pslist envía la señal dada (o SIGTERMpor defecto) al proceso especificado y a todos sus descendientes:

rkill [-SIG] pid/name...

0

Otra opción para matar a todos los descendientes del caparazón: jobs -p | xargs -n 1 pkill -P

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.