Aqui está o meu roteiro:
#! /bin/bash
ret=0
file_out1=$(mktemp)
file_out2=$(mktemp)
(echo first start; sleep 2s; echo first finish;) &> $file_out1 &
ret=$?
P1=$!
(echo second start; sleep 1s; echo second finish;) &> $file_out2 &
ret=$?
P2=$!
wait $P1 $P2 || ret=$?
cat $file_out1
cat $file_out2
exit $ret
Aqui, a saída é:
first start
first finish
second start
second finish
Mas a saída deve ser:
second start
second finish
first start
first finish
O que quero dizer é, cat $file_out1
deve ser executado assim que P1
for concluído e cat $file_out2
deve ser executado assim que P2
for concluído.
Além disso, quero ter certeza de que P1 terminou com sucesso e P2 terminou com sucesso. No final, como posso saber se houve um erro em P1
ou P2
ou ambos.
Neste script, $ret
não está funcionando corretamente (é sempre exit 0
). Depois que funcionar, seria bom saber se era $ret
de P1
ou P2
. Diga algo como P1
código de retorno x1, P2
código de retorno x2. E saia do programa com um código de retorno diferente de zero se houver um código de saída diferente de zero.
Atualização1:
Uma resposta em askubuntu , sugere que podemos usar --group
o argumento do comando paralelo para garantir que a saída de cada comando aguarde até que o comando seja concluído (evita saída mista).
O comando que mostrou é parallel --group 'echo -n {};sleep {};echo {}' ::: 1 3 2 4
.
Este comando funciona na minha máquina. No entanto, não estou entendendo como usar esse comando no meu contexto.
Quero dizer, como posso obter
second start
second finish
first start
first finish
Quando os comandos de entrada são echo first start; sleep 2s; echo first finish;
e echo second start; sleep 1s; echo second finish;
usando gnu parallel.
Atualização 2:
O código em que estou atualmente é:
#! /bin/bash
function first {
echo first start
sleep 2s
echo first finish
}
function second {
echo second start
sleep 1s
echo second finish
}
export -f first && export -f second
parallel -j2 ::: first second
Isso realmente resolve meu problema.
Suponho que você espera que cada uma de suas tarefas mostre a saída assim que terminar, mas evite dobrar a saída, é por isso que você armazena em buffer em um arquivo - tudo bem, você também pode prefixar a saída com sed, deixe fluir como vem, em seguida, classifique-o novamente sob demanda: isso seria em caso de quantidade imprevisível de dados e risco de estouro de armazenamento.
Seus erros:
&
, perde o acesso ao status final (o que você esperaret=$?
é outra coisa)wait
a tempo de capturar o status final de cada processo: muito tarde após o término do processo,wait
obterá127
mesmo se o status final do processo for0
. E isso é imprevisível.Seu desejo é ter o mesmo feedback da execução sequencial, mas com a vantagem de duração do paralelismo e minimizando o molho.
Deixe-os executar em sua própria caixa, gerencie a corrida pela saída -
flock
em um descritor de arquivo está limpo - e force-os a registrar seu status final em algum lugar - novamente, um descritor de arquivo está limpo.EDIT GNU parallel foi uma solução completa, como diz a edição de @AhmadIsmail. Deixe este de qualquer maneira.