Pegue este script bash simples e burro que apenas inicia dois subprocessos (um em segundo plano, o outro esperando):
#!/bin/bash
sleep 40 & sleep 41
Execute, aqui está a árvore do processo:
PID PGID STAT CMD
8709 8709 Ss /bin/zsh
14431 14431 S+ \_ sh ./runsubprocess
14432 14431 S+ \_ sleep 40
14433 14431 S+ \_ sleep 41
Em seguida, mate-o com kill 14431
, aqui está a árvore do processo:
PID PGID STAT CMD
14432 14431 S sleep 40
14433 14431 S sleep 41
Deixamos dois processos em execução 🙁
Solução: use pkill para matar as crianças também!
Mate-o pkill -P 14431
e agora você não terá mais órfãos.
pkill matará o processo e seus filhos, não os netos!
Imagine que você tem este script:
#!/bin/bash
(sleep 40 & sleep 41) & sleep 42
Árvore de processos:
PID PGID STAT CMD
8709 8709 Ss /bin/zsh
14431 14431 S+ \_ sh ./runsubprocess
14432 14431 S+ \_ sleep 41
14434 14431 S+ | \_ sleep 40
14433 14431 S+ \_ sleep 42
Usando pkill -P 14431
você ainda deixa este processo para trás:
PID PGID STAT CMD
14434 14431 S sleep 40
Foda-se! Mas aí vem o PGID (Id do Grupo de Processo). Observe como todo processo originalmente iniciado pelo mesmo ancestral tem o mesmo PGID (aqui 14431). Funciona assim, define os subprocessos e sua raiz original. O processo raiz geralmente tem PID = PGID. E, oh, matar pode matar por PGID se prefixar com uma pitada: .kill -TERM -$PGID
Usar é a maneira melhor e mais fácil de alcançar o que procurávamos.kill -TERM -14431
Notas adicionais:
→ Eu costumava ps fo pid,pgid,stat,cmd
mostrar as árvores de processo da maneira como são coladas aqui 🙂
→ Os processos mantêm seu PGID original, mesmo que o ancestral tenha morrido. Você ainda pode matar por PGID se você esqueceu alguns órfãos.
→ Suponho que você possa enfrentar exceções, então se o processo root for PID ≠ PGID, você ainda pode obter o PGID do PID:echo $PID |xargs echo | xargs -i ps -o pgid -p {}|xargs echo |awk '{print $2}'