Como obter o PID de um subprocesso através do processo pai em um script de shell bash?

4

Meu script de shell é o seguinte:

#!/bin/bash
./process1 #It will create a sub process: sub_process1
while [ condition ]; do
    break
done
kill -9 process1 and sub_process1

No meu script, ele criará um processo: process1. O processo1 criará um subprocesso: sub_process1.
Antes do script terminar, ele precisa matar o process1 e o sub_process1. É fácil eliminar o processo1, pois ele gravará o PID em um arquivo. Mas o sub_process1 não. Como o sub_process1 é um componente de terceiros, não consigo tocar no código-fonte.
Existe uma solução que pode obter o PID de sub_process1:

  1. Enumere todos os processos com o comando ps aux ;
  2. Obtenha o PPID (ID do processo pai) para cada processo com o comando ps -f [PID] . Se o PPID for igual ao PID do processo1, o processo deverá ser sub_processo1. A solução acima é um pouco complicada. Existe uma solução simples que pode obter o ID do subprocesso?
    Muito obrigado.
por yw5643 22.05.2015 / 12:29

4 respostas

2

Desde que você marcou isso como Linux: pgrep / pkill para o resgate:

PID_OF_SUB_PROCESS1=$( pgrep -P $PID_OF_PROCESS1 )
pkill -P $PID_OF_PROCESS1
    
por 22.05.2015 / 12:50
0

O que você pode fazer é kill -TERM you grupo de processos . Se o seu script for chamado a partir de um shell, ele terá seu próprio grupo de processos igual ao PID do script:

kill -TERM -$$

Se for invocado, o ID do grupo de processos pode não ser igual ao seu PID:

kill -TERM -'ps -o pgid $$ | tail -1'

Você não deve kill -9 em um script ou programa, a menos que você conceda ao programa uma chance justa com kill -TERM .

Fazer um find pid and kill it está sujeito a condições de corrida (embora eles não demonstrem com frequência, a menos que sua caixa gere processos como um louco). pid s é um alvo em movimento e a menos que o pid que você está matando seja seu filho e você tenha assegurado que o pid não será reciclado por não esperar por ele (algo que dificilmente você pode fazer na medida em que eu saiba ), você não pode ter 100% de certeza de estar matando o processo correto (entre encontrar um pid e matar, o processo pode ter morrido e outro pode ter tomado o pid).

    
por 22.05.2015 / 13:45
0

pkill pode matar processos por nome :

pkill process1 && pkill sub_process1

deve fazer o trabalho.

    
por 22.05.2015 / 15:13
0

Você pode obter o ID do processo de process , executando-o como um processo em segundo plano.

./process1 &
pid1=$!
wait "$pid1"

O comando wait aguarda que process1 saia (mas não seus subprocessos), como em seu script original. Observe que em seu script original, não há process1 para matar no final: o comando ./process1 é concluído apenas quando process1 é encerrado. É possível que exista um processo filho desse processo com o mesmo nome (ou seja, o programa pode ter chamado fork mas não execve ). Se você quiser continuar executando o script assim que o process1 for iniciado, omita a linha wait .

Se você tiver o comando pkill , é uma maneira conveniente de matar todos os filhos de um processo . Observe que o processo ainda deve estar em execução ou deve ser um zumbi , caso contrário, o ID do processo pai das crianças será redefinido para 1 e você não pode mais rastreá-los dessa maneira. Contanto que você não tenha chamado wait em seu script, a ID do processo em segundo plano permanecerá válida.

./process1 &
pid1=$!
…
pkill -9 -P "$pid1"
kill -9 "$pid1"

Outra maneira de acompanhar um processo, seus filhos e seus filhos de forma recursiva é acompanhar o grupo de processos . Os filhos de um processo têm o mesmo grupo de processos, a menos que eles o modifiquem explicitamente. No Linux, você pode usar o comando setsid para executar um programa em seu próprio grupo de processos. O grupo de processos é identificado pelo ID do processo original. Para eliminar todos os processos em um grupo de processos, passe o negativo do ID do grupo de processos para kill .

setsid ./process1 &
pgid1=$!
…
kill -9 "-$pgid1"

No entanto, outra maneira de rastrear processos é fazer com que eles abram um arquivo. Isso funciona desde que os processos não fechem os arquivos, portanto, pode não funcionar para um programa que deve ser executado como um daemon. Use o comando fuser para eliminar os processos que possuem o arquivo aberto.

tmpfile=$(mktemp)
process1 <"$tmpfile"
…
fuser -k -9 "$tmpfile"
    
por 23.05.2015 / 02:01