如何运行并行进程并在两个进程完成后合并输出

如何运行并行进程并在两个进程完成后合并输出

我有一个 bash shell 脚本,其中我通过大约 5 或 6 个不同的程序传输一些数据,然后将最终结果放入制表符分隔的文件中。

然后,我对一个单独的相似数据集再次执行相同的操作,并将其输出到第二个文件。

然后将这两个文件输入到另一个程序中进行比较分析。例如简化

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

我的问题是:如何使步骤 1 和步骤 2 同时运行(例如使用 &),但仅在两者完成时启动步骤 3(AnalysisProg)?

谢谢

ps AnalysisProg 不适用于流或 fifo。

答案1

使用wait。例如:

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

将要:

  • 将 Data1 和 Data2 管道作为后台作业运行
  • 等他们俩完成
  • 运行 AnalysisProg。

参见,例如,这个问题

答案2

如果你只有 2 个文件,cxw 的答案无疑是更好的解决方案。如果这 2 个文件只是示例,而您实际上有 10000 个文件,那么“&”解决方案将不起作用,因为这会使您的服务器超载。为此,您需要像 GNU Parallel 这样的工具:

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

要了解有关 GNU Parallel 的更多信息:

答案3

执行此操作的一种方法可能类似于:

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

通过这种方式,您可以将两个管道设置为后台,但仍然等待它们完成执行,然后再将它们的输出合并到标准输入中,该标准输入在此处文档中进行评估并交给 AnalysisProg。如果你可以使用wait这甚至比while ps循环,但是,取决于外壳,wait如果您指示它等待某个进程,则可以反对不是当前 shell 的子级。

另请注意,上述方法将整理输出 - 因此两个进程将同时写出。如果您希望将它们分开,或者将它们附加到另一个上,您可以这样做:

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

我之前已经演示过这些概念。最好的演示可能是这里这里

答案4

尝试使用这个。

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

相关内容