Inicie um novo grupo de processos para o código Python (usando o setsid utilitário) e quaisquer outros processos (incluindo o próprio aplicativo), assim você pode matar todo o grupo de processos, se necessário.
Você pode usar a seguinte construção para fazer isso:
exec 3>&1
pgid=$(exec setsid bash -c 'echo $$; exec >&3-; exec COMMAND...')
onde COMMAND... é o comando e seus parâmetros que você normalmente iniciaria. Observe que ele está entre aspas simples e que o comando a ser executado deve ser avaliavel como uma string (em oposição a uma expressão de shell normal).
O primeiro redirecionamento, 3>&1 , copia o descritor de saída padrão para o descritor 3. O redirecionamento >&3- move o descritor 3 para a saída padrão.
O $(...) executa o ... e avalia os dados que ele gravou na saída padrão. Acima, lemos a saída padrão na variável do shell pgid .
O subshell ( ... ) é substituído pelo utilitário setsid , que executa seu argumento em uma nova sessão (grupo de processos). Aqui, ele executa bash , que imprime o processo atual PID ( $$ ), move a saída padrão original do descritor 3 para trás e se substitui / executa o COMMAND... desejado.
O shell executará essa linha enquanto o COMMAND... for executado e só avançará para a próxima linha após a saída de COMMAND... .
Se o COMMAND... deixar processos espúrios em execução e você quiser eliminá-los, tudo que você precisa fazer é executar
kill -SIGNAL -$pgid
A questão é qual sinal enviar. KILL eliminará imediatamente os processos restantes no grupo de processos, por isso é a opção mais simples. No entanto, se os processos se comportarem bem, você poderá pedir que eles saiam enviando-lhes um sinal TERM . É claro que, às vezes, os processos podem ficar em estado instável, de modo que não reajam a TERM e precisem ser KILL ed. Para resolver isso, você pode usar um pequeno loop e ps para ver se ainda há algum processo:
retries=50
while ((1)); do
# Processes left?
left=$(ps -o pid= -s $pgrp)
[ -n "$left" ] || break
# Ask them to terminate.
kill -TERM $left
# Wait 0.1 seconds.
sleep .1
# Decrement the retry counter.
((--retries > 0)) || break
done
# If there are any processes left in the group,
# send them a KILL signal.
left=$(ps -o pid= -s $pgrp)
[ -n "$left" ] && kill -KILL $left
Observe que as 50 tentativas (0,1 segundo cada) significam que isso espera apenas até 5 segundos antes de enviar um sinal de eliminação. Isso pode não ser um valor adequado, dependendo do aplicativo e do tipo de hardware em execução. Por exemplo, se a máquina for um laptop, e o aplicativo salvar algum histórico ou registros em vários arquivos, e a unidade estiver dormindo no ponto de saída, aumentarei o atraso para talvez 15 a 30 segundos. / p>