Como executar processos paralelos e combinar resultados quando ambos terminarem

Como executar processos paralelos e combinar resultados quando ambos terminarem

Eu tenho um script de shell bash no qual canalizo alguns dados por cerca de 5 ou 6 programas diferentes e, em seguida, os resultados finais em um arquivo delimitado por tabulações.

Em seguida, faço o mesmo novamente para um conjunto de dados semelhante separado e envio para um segundo arquivo.

Em seguida, ambos os arquivos são inseridos em outro programa para análise comparativa. por exemplo, para simplificar

Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv
AnalysisProg -i Data1res.csv Data2res.csv

Minha pergunta é: como posso executar a etapa 1 e a etapa 2 ao mesmo tempo (por exemplo, usando &), mas apenas iniciar a etapa 3 (AnalysisProg) quando ambas estiverem concluídas?

THX

ps AnalysisProg não funcionará em um stream ou fifo.

Responder1

Usar wait. Por exemplo:

Data1 ... > Data1Res.csv &
Data2 ... > Data2Res.csv &
wait
AnalysisProg

vai:

  • execute os pipes Data1 e Data2 como trabalhos em segundo plano
  • espere os dois terminarem
  • execute AnalysisProg.

Veja, por exemplo,essa questão.

Responder2

A resposta do cxw é sem dúvida a solução preferível, se você tiver apenas 2 arquivos. Se os 2 arquivos forem apenas exemplos e você realmente tiver 10.000 arquivos, a solução '&' não funcionará, pois sobrecarregará seu servidor. Para isso você precisa de uma ferramenta como o GNU Parallel:

ls Data* | parallel 'cat {} | this | that |theother | grep |sed | awk |whatever > {}res.csv
AnalysisProg -i *res.csv

Para saber mais sobre o GNU Paralelo:

Responder3

Uma maneira de fazer isso pode ser algo como:

AnalysisProg <<PREPROCESS /dev/stdin
$( 
{   process1=$( pipe | line | 1 >&2 & echo $! )
    process2=$( pipe | line | 2 >&2 & echo $! )
    while ps -p $process1 $process2 >/dev/null; do
        sleep 1
    done
} 2>&1
)
#END
PREPROCESS

Dessa forma, você coloca em segundo plano ambos os pipelines, mas ainda espera que eles terminem a execução antes de combinar sua saída em stdin, que é avaliado em um documento aqui e entregue ao AnalysisProg. Se você pode usarwaitisso é ainda melhor do que owhile psloop, mas, dependendo do shell,waitpode objetar se você instruí-lo a aguardar um processo quenão é filho do shell atual.

Observe também que o método acima agrupará a saída - portanto, ambos os processos serão gravados ao mesmo tempo. Se você quiser separá-los ou anexá-los um ao outro, poderá fazer:

AnalysisProg 3<<PREPROCESS /dev/fd/3 /dev/stderr
$(
process1=$(... >&2 ...) 2>/dev/fd/3
...
} 3>/dev/fd/3 2>/dev/stderr
)

Já demonstrei esses conceitos antes. Provavelmente as melhores demos sãoaquieaqui.

Responder4

Tente usar isso.

rm -f Data1Res.csv
rm -f Data2Res.csv
Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv &
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv &
while true
do
  ps aux | grep -v grep | grep -i -E 'Data1Res.csv|Data2Res.csv' &> /dev/null
  if [ $? -ne 0 ]
  then
    AnalysisProg -i Data1res.csv Data2res.csv
    exit 0
  fi
done

informação relacionada