Se algum processo spawned filho falhar, mate todos e saia

8

No meu script eu divido um conjunto de dados em input_aa, input_ab, etc. Então, eu corro cada um pelo mesmo script Python, como tal:

# Execute program on each split file
for part in input_*; do
        python3 $part &
done
wait

Minha pergunta é dupla: como eu detecto que um processo Python falhou e, quando detectado, como faço para matar todos os filhos gerados e sair do script com uma falha?

    
por Befall 14.01.2015 / 20:18

2 respostas

9

Você pode usar um grupo de processos:

set -m
(
   for part in input_*; do
     (python3 "$part" || kill 0) &
   done
   wait
)

set -m (e o recurso de shell POSIX opcional, necessário ao recurso de shell Unix) executa tarefas em seu próprio grupo de processos. Em bash , yash , zsh , mksh , são os jobs da subshell em que set -m está habilitado, de forma que o% outer(...) e todos os processos criados nele sejam colocados nesse mesmo grupo de processos.

Para dash e outros shells baseados em ash , isso só funciona no processo de shell de nível superior. Então, esse código funcionará, a menos que seja colocado em uma subcamada.

Isso não funcionará em AT & T ksh ou no antigo shell SysV / Bourne.

kill 0 envia um sinal SIGTERM para todos os membros do grupo de processos atual.

    
por 14.01.2015 / 23:24
3

Este é um exemplo. JOGUE com isso primeiro para obter exatamente o que você precisa. Não pode quebrar muito como é.

#!/bin/bash
# Example of killing off all children

> killfile
> outfile.err
kill_em()
{
   echo 'killing all children ' > 2
   while read pid
   do
      kill -0 $pid && kill -9 $pid  # if still running kill it
   done < killfile
   exit 1
}

export grandparentpid=$$
trap 'kill_em' 6
for i in 2 2 3 4 5 6 7 8 9 10
do
        ( sleep $i && ls oinkle  >> outfile 2>> outfile.err &
          pid=$!
          echo $pid >> killfile
          wait $!
          [ $? -ne 0 ] && kill -6 $grandparentpid
        ) &
done
wait

Isso está configurado para falhar deliberadamente porque ls oinkle falhará (na minha máquina).

Quando você obtiver o que precisa depois de mexer no script inicial --- Alterar:

for i in 2 2 3 4 5 6 7 8 9 10

para:

for part in input_* 

mudança:

sleep $i && ls oinkle 

para:

python3 $part 

Os redirecionamentos estão lá para salvar registros. Você pode não querer eles.

    
por 14.01.2015 / 21:19