Processar descendentes

16

Estou tentando criar um contêiner de processo. O contêiner acionará outros programas. Por exemplo, um script bash que inicia a execução de tarefas em segundo plano com '&' uso.

A característica importante que estou procurando é a seguinte: quando eu mato o contêiner, tudo o que foi gerado sob ele deve ser eliminado. Não apenas os filhos diretos, mas seus descendentes também.

Quando comecei este projeto, acreditei erroneamente que, quando você matava um processo, seus filhos também eram mortos automaticamente. Eu procurei conselhos de pessoas que tiveram a mesma ideia incorreta. Embora seja possível capturar um sinal e passar a morte para as crianças, não é isso que estou procurando aqui.

Eu acredito no que eu quero ser viável, porque quando você fecha um xterm, qualquer coisa que esteja rodando dentro dele é morta a menos que seja nohup'd. Isso inclui processos órfãos. É isso que eu estou tentando recriar.

Eu tenho uma ideia de que o que estou procurando envolve sessões unix.

Se houvesse uma maneira confiável de identificar todos os descendentes de um processo, seria útil poder enviá-los sinais arbitrários também. por exemplo. SIGUSR1.

    
por Craig Turner 11.06.2011 / 12:59

5 respostas

18

Se você enviar um sinal para um processo, esse processo será eliminado. Eu me pergunto como o boato de que matar um processo também mata outros processos iniciados parece particularmente contra-intuitivo.

Existem, no entanto, maneiras de matar mais de um processo. Mas você não estará enviando um sinal para um processo. Você pode matar todo um grupo de processos enviando um sinal para -1234, onde 1234 é o PGID (process group ID), que é o PID do líder do grupo de processos. Quando você executa um pipeline , todo o pipeline começa como um grupo de processos (os aplicativos podem alterar isso chamando setpgid ou setpgrp ).

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á nenhuma facilidade para matar uma sessão inteira ou mesmo para enumerar os grupos de processos ou processos em uma sessão, de modo que não ajuda muito.

Quando você fecha um terminal, o kernel envia o sinal SIGHUP para todos os processos que o têm como < href="http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_114"> controle do terminal . 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, criado por script , tela , etc. Mate o processo do emulador de terminal para eliminar os processos contidos (supondo que eles t dividido com setsid ).

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 de sistema ou o < um href="http://pubs.opengroup.org/onlinepubs/009695399/utilities/kill.html"> utilitário ) como esse usuário e use -1 como o argumento PID para matar, significando “tudo isso processos do usuário ”.

Você pode fornecer ainda mais isolamento, mas com consideravelmente mais configurações, executando os processos contidos em um contêiner .

    
por 12.06.2011 / 13:50
2

Uma maneira confiável de identificar todos os descendentes de um processo é usar o comando pstree <pid> , em que pid é o ID do processo pai.

Leia a página man em pstree aqui .

Para sinalizar todos os membros de um grupo de processos: killpg(<pgrp>, <sig>);
onde pgrp é o número do grupo de processos e sig é o sinal.

Para esperar por crianças em um grupo de processos especificado: waitpid(-<pgrp>, &status, ...);

Uma alternativa ao que você está fazendo é executar o contêiner de processo em um novo shell bash. Crie o novo shell bash com o comando bash e, em seguida, execute seus processos. Quando você quiser que todos os processos sejam finalizados, saia do shell com o comando exit .

    
por 11.06.2011 / 18:27
2

Dentro do script pai, prenda o sinal kill e mate todos os filhos. Por exemplo,

#!/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
    
por 16.03.2015 / 19:32
1

Use

unshare -fp --kill-child -- yourprogram

Se você matar unshare , todos os processos filhos (que yourprogram podem ter gerado) serão mortos.

Isso agora é possível com o util-linux 2.32 ; Eu implementei este upstream . Ele requer namespaces de usuário (opção de configuração do kernel CONFIG_USER_NS=y ) ou privilégios de root. Veja também aqui .

    
por 17.06.2018 / 05:03
0

rkill do pacote pslist envia um determinado sinal (ou SIGTERM por padrão) para processo especificado e todos os seus descendentes:

rkill [-SIG] pid/name...
    
por 06.11.2015 / 05:59