我有两个命令行程序,通常在 Linux 系统上串行运行。
这两个程序的典型执行如下:
- 程序A运行。它输入一个简单的文本文件,输出一个简单的文本文件。
- 程序B在A之后运行,其输入是程序A产生的文本文件。它还输出一个简单的文本文件。
注意:对于上述两个程序,它们的输入和输出只是各自输入和输出文件的路径。示例: $ prog_a /path/to/inputfile/dataIn.txt /path/to/outputfile/dataOut.txt $ prog_b /path/to/inputfile/dataOut.txt /path/to/outputfile/results.txt
这些是由第三方开发的程序。因此我们不能轻易修改它们(至少不能及时修改)。然而,我们希望通过使用命名管道并行运行它们来加快执行速度。数据文件有时非常大,我们认为并行处理会加快速度。我接受了这个项目的任务,并按如下方式进行。
编写了一个 bash 脚本,其中:
- 创建一个链接两个程序的命名管道。将其命名为 dataOut.pipe
- 程序 A 像往常一样读入文本文件,但不是像以前那样写入文本文件,而是写入步骤 1 中创建的管道 dataOut.pipe
- 程序 B 读入程序 A 输出的管道。
bash 脚本看起来像这样:
\#!/bin/bash
mkfifo dataOut.pipe
prog_b dataOut.pipe results.txt &
prog_a dataIn.txt dataOut.pipe
rm dataOut.pipe
现在这有效......有时......很多时候我得到一个java异常吐出到stderror。我无法弄清楚问题到底是什么,但我认为是这样的:
程序 B 有时会比 A 运行得更快,并且清理管道的速度会比 A 将数据放入其中的速度更快,从而导致整个事情崩溃吗?
如果是这种情况,有什么简单的解决方法吗?或者还有其他事情发生吗?
答案1
损坏的管道意味着写入器 (prog_a) 正在尝试写入已损坏的管道关闭由其读者(prog_b)。您没有向我们提供足够的信息来弄清楚为什么 prog_b 停止得这么快。
也就是说,您假设 prog_b 按顺序读取其输入文件,直到满足 EOF,并在读取时处理每一行,就像常规的 Unix 过滤命令一样。你确定吗?如果 prog_b 想要查找它的输入文件,或者 mmap 它,你就注定失败(prog_a 也是如此)。如果 prog_b 想要读取所有输入行然后才处理它们,那么并行化 prog_a 和 prog_b 几乎不会实现任何目标,因为 prog_b 仅在管道关闭时(即 prog_a 结束时)才会开始处理。