Cómo ejecutar procesos paralelos y combinar salidas cuando ambos hayan terminado

Cómo ejecutar procesos paralelos y combinar salidas cuando ambos hayan terminado

Tengo un script de shell bash en el que canalizo algunos datos a través de aproximadamente 5 o 6 programas diferentes y luego los resultados finales en un archivo delimitado por tabulaciones.

Luego hago lo mismo nuevamente para un conjunto de datos similar separado y lo envío a un segundo archivo.

Luego, ambos archivos se ingresan en otro programa para su análisis comparativo. por ejemplo, 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

Mi pregunta es: ¿cómo puedo hacer que el paso 1 y el paso 2 se ejecuten al mismo tiempo (por ejemplo, usando &) pero solo inicie el paso 3 (AnalysisProg) cuando ambos estén completos?

Gracias

ps AnalysisProg no funcionará en una secuencia o quince.

Respuesta1

Usar wait. Por ejemplo:

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

voluntad:

  • ejecutar las canalizaciones Data1 y Data2 como trabajos en segundo plano
  • espera a que ambos terminen
  • ejecute AnalysisProg.

Ver, por ejemplo,esta pregunta.

Respuesta2

La respuesta de cxw es sin duda la solución preferible, si solo tiene 2 archivos. Si los 2 archivos son solo ejemplos y en realidad tiene 10000 archivos, entonces la solución '&' no funcionará, ya que sobrecargará su servidor. Para eso necesitas una herramienta como GNU Parallel:

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

Para obtener más información sobre GNU Parallel:

Respuesta3

Una forma de hacer esto podría verse así:

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

De esta manera, usted pone en segundo plano ambas canalizaciones pero aún espera a que terminen de ejecutarse antes de combinar su salida en la entrada estándar que se evalúa en un documento aquí y se entrega a AnalysisProg. Si puedes usarwaitesto es incluso mejor que elwhile psbucle, pero, dependiendo del caparazón,waitpuede objetar si le indica que espere en un proceso queno es hijo del shell actual.

También tenga en cuenta que el método anterior cotejará la salida, por lo que ambos procesos escribirán a la vez. Si, en cambio, quisiera separarlos o agregarlos uno al otro, posiblemente podría hacer:

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

He demostrado estos conceptos antes. Probablemente las mejores demostraciones sonaquíyaquí.

Respuesta4

Intenta usar esto.

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

información relacionada