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.
SIGHUP
a 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.Respuestas:
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
setpgid
osetpgrp
).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
SIGHUP
a 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 separadosetsid
).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 .
fuente
prctl(PR_SET_PDEATHSIG, SIGHUP);
más información: man7.org/linux/man-pages/man2/prctl.2.htmlDentro del script principal, atrape la señal de muerte y haga que mate a todos los niños. Por ejemplo,
fuente
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
bash
y luego ejecute sus procesos. Cuando desee que finalicen todos los procesos, salga del shell con el comandoexit
.fuente
Utilizar
Si matas
unshare
, todos los procesos secundarios (queyourprogram
pueden 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úcleoCONFIG_USER_NS=y
) o privilegios de root. Ver también aquí .fuente
El comando rkill del paquete pslist envía la señal dada (o
SIGTERM
por defecto) al proceso especificado y a todos sus descendientes:fuente
Otra opción para matar a todos los descendientes del caparazón:
jobs -p | xargs -n 1 pkill -P
fuente