Estou tentando construir um contêiner de processo. O contêiner acionará outros programas. Por exemplo - um script bash que inicia tarefas em segundo plano em execução com o uso de '&'.
A característica importante que procuro é a seguinte: quando eu matar o contêiner, tudo o que foi gerado por ele deve ser morto. Não apenas filhos diretos, mas também seus descendentes.
Quando iniciei este projeto, acreditei erroneamente que quando você matava um processo, os filhos também eram automaticamente mortos. Procurei conselhos de pessoas que tiveram a mesma ideia incorreta. Embora seja possível captar um sinal e transmitir a morte para as crianças, não é isso que estou procurando aqui.
Eu acredito no que eu quero que seja possível, porque quando você fecha um xterm, qualquer coisa que esteja sendo executada nele é morta, a menos que não tenha sido copiada. Isso inclui processos órfãos. É isso que estou procurando recriar.
Eu tenho uma idéia de que o que eu estou procurando envolve sessões unix.
Se houvesse uma maneira confiável de identificar todos os descendentes de um processo, seria útil poder enviar a eles também sinais arbitrários. por exemplo, SIGUSR1.
SIGHUP
para os processos filhos diretos. O manipulador padrão do sinal de desligamento interrompe a execução do processo, portanto a rota padrão é matar todos os descendentes. Leia mais sobre processos e grupos de processos.Respostas:
Se você enviar um sinal para um processo, esse processo será interrompido. Eu me pergunto como começou o boato de que matar um processo também mata outros processos, parece particularmente contra-intuitivo.
No entanto, existem maneiras de matar mais de um processo. Mas você não estará enviando um sinal para um processo. Você pode eliminar todo um grupo de processos enviando um sinal para -1234, em que 1234 é o PGID (ID do grupo de processos), que é o PID do líder do grupo de processos. Quando você executa um pipeline , o pipeline inteiro inicia como um grupo de processos (os aplicativos podem mudar isso chamando
setpgid
ousetpgrp
).Quando você inicia processos em segundo plano (
foo &
), eles estão em seu próprio grupo de processos. Grupos de processos são usados para gerenciar o acesso ao terminal; normalmente apenas o grupo de processos em primeiro plano tem acesso ao terminal. Os trabalhos em segundo plano permanecem na mesma sessão , mas não há possibilidade de matar uma sessão inteira ou até de enumerar os grupos ou processos de uma sessão, de modo que isso não ajuda muito.Quando você fecha um terminal, o kernel envia o sinal
SIGHUP
para todos os processos que o possuem como terminal de controle . Esses processos formam uma sessão , mas nem todas as sessões têm um terminal de controle. Para o seu projeto, uma possibilidade é, portanto, iniciar todos os processos em seu próprio terminal, criados por script , tela etc. Mate o processo do emulador de terminal para matar os processos contidos (supondo que eles não tenham se separadosetsid
).Você pode fornecer mais isolamento executando os processos como seu próprio usuário, que não faz mais nada. Então é fácil eliminar todos os processos: execute
kill
(a chamada do sistema ou o utilitário ) como esse usuário e use -1 como argumento PID para eliminar, significando "todos os processos desse usuário".Você pode fornecer ainda mais isolamento, mas com consideravelmente mais configuração executando os processos contidos em um contêiner real .
fonte
prctl(PR_SET_PDEATHSIG, SIGHUP);
, mais informações: man7.org/linux/man-pages/man2/prctl.2.htmlNo script pai, prenda o sinal de matança e faça com que mate todos os filhos. Por exemplo,
fonte
Uma maneira confiável de identificar todos os descendentes de um processo é usar o comando em
pstree <pid>
que pid é seu ID de processo pai.Leia a página de manual
pstree
aqui .Para sinalizar todos os membros de um grupo de processos: em
killpg(<pgrp>, <sig>);
que pgrp é o número do grupo de processos e sig é o sinal.
Para aguardar filhos em um grupo de processos especificado:
waitpid(-<pgrp>, &status, ...);
Uma alternativa ao que você está fazendo é executar o contêiner do processo em um novo shell bash. Crie o novo shell bash com o comando
bash
e execute seus processos. Quando você quiser que todos os processos a serem encerrados, sair do shell com o comandoexit
.fonte
Usar
Se você matar
unshare
, todos os processos filhos (queyourprogram
podem ter gerado) serão mortos.Agora isso é possível com o util-linux
2.32
; Eu implementei isso a montante . Requer espaços de nome de usuário (opção de configuração do kernelCONFIG_USER_NS=y
) ou privilégios de root. Veja também aqui .fonte
O comando rkill do pacote pslist envia o sinal fornecido (ou
SIGTERM
por padrão) para o processo especificado e todos os seus descendentes:fonte
Outra opção para matar todos os descendentes da concha:
jobs -p | xargs -n 1 pkill -P
fonte