suponha que eu queira executar alguns (digamos, três) programas ao mesmo tempo, como este
program1 & program2 & program3 &
se eu quiser saber deles pid's
, acho que a melhor maneira é armazená-los, assim
program1 &
pid1=$!
program2 &
pid2=$!
...
Mas agora, e se eu quiser saber se eles terminaram e se sim, qual o valor que retornaram? Algo assim:
if [ program1 has ended ]; then
do something with its return value
fi
Qualquer ajuda será apreciada
Responder1
# launch child process in background
launch_child_process &
# grab child's pid and store it (use array if several)
pid=$!
# later, wait for termination
wait $pid
# show return code from wait, which is actually the return code of the child
echo "Child return code:" $?
Com vários filhos, é claro que você pode fazer um loop para aguardar cada pid e coletar o código de retorno correspondente. Você sai desse ciclo quando o último filho termina.
Responder2
Uma solução simples é escrever uma mensagem em um arquivo de log
Digamos, para o programa 1, faça algo como:
#!/bin/bash
.
.
your stuff
.
.
end_time==$(date)
echo "program1 ended at $end_time" > program1_log
Outra solução seria criar um arquivo vazio para marcar o fim do processo
#!/bin/bash
.
.
your stuff
.
.
echo $? > /some/path/program1_ended #storing the exit value
#disadvantage is that you can't verify if intermediate commands failed.
Então para verificar faça
if [ -e /some/path/program1_ended ]
then
exit_status=$( </some/path/program1_ended )
rm /some/path/program1_ended #Deleting the file, getting ready for next run
.
.
Do something
else
echo "program1 has not ended yet"
fi
Responder3
POSIX sh não é muito bom para lidar com vários processos em segundo plano. A ferramenta básica é a wait
interna, que bloqueia até que um processo em segundo plano seja encerrado. Mas wait
sem nenhum argumento espera atétodosos processos em segundo plano foram encerrados e retorna o status de saída do último processo encerrado; o status de saída dos outros subprocessos é perdido.
Você pode definir uma armadilha para SIGCHLD, que é o sinal gerado quando o filho de um processo é encerrado. Isso executa o código sempre que um subprocesso é encerrado. No entanto, você não necessariamente sabe qual subprocesso foi encerrado ou qual é seu status de retorno. Diferentes shells se comportam de maneira diferente.
ATT ksh93 (não mksh ou pdksh!) é o único entre os shells comuns que se comporta de maneira útil com armadilhas SIGCHLD. Define $!
o PID do processo que saiu e $?
seu status de retorno.
#!/bin/ksh
trap 'Process $! (${subprocesses[$!]}) exited with status $?' CHLD
typeset -A subprocesses
program1 & subprocesses[$!]='program1'
program2 & subprocesses[$!]='program2'
wait
Se você usar outra casca, coloque qualquer pós-tratamento no subprocesso.
#!/bin/sh
{ program1; echo "program1 exited with status $?"; } &
{ program2; echo "program2 exited with status $?"; } &
wait
Ou use uma linguagem mais capaz, como Perl, Python, Ruby, etc.
Responder4
Se você souber em que ordem os processos terminarão, aproximadamente, poderá usar wait <pid>
para aguardar a saída, e o wait
comando herdará o status de saída do processo esperado. por exemplo
if wait $pid1
then echo "$pid1 was ok"
else echo "$pid1 failed with code $?"
fi
Se você não sabe o pedido, pode esperar por qualquer um deles wait -n $pid1 $pid2 ...
e obter o código de saída da mesma forma, mas não saberá qual processo terminou, mas é útil se você precisar apenas saber se algum falhou.