我有一个 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 的更多信息:
- 观看介绍视频以进行快速介绍: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
- 浏览本教程 (man parallel_tutorial)。你的命令行会喜欢你的。
答案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