使用无缓冲管道作为“虚拟”文件输出

时间:2018-01-14 21:23:58

标签: linux bash pipe buffer stdout

我一直在处理一个我无法找到解决方法的奇怪问题。

我的情况如下。

我在python中有一个名为“app1”的应用程序,需要一个文件来输出它的执行结果。

我有一个名为“app2”的辅助应用程序;二进制文件,从stdin获取输入

我想管道“app1”直接生成“app2”进行处理,在理想情况下会是这样的:

app1 | app2

但是,正如我所说,有一些限制,比如app1 需要一个文件作为输出。 我发现“愚弄”app1输出到stdout的第一个解决方案是使用mkfifo并创建一个管道,所以我可以将它管道输入到app2中的stdin。像这样:

pipe='/tmp/output_pipe'
mkfifo "$output_pipe"

python app1 -o "$output_pipe" &
app2 < $tmp_pipe

问题是最终,在执行期间,app1将生成比app2作为输入处理的输出更多的输出,并且由于管道上的缓冲区大小限制,管道将填满一切都会停止工作。

然后我使用了另一种方法:

python app1 -o /dev/stdout | app2

但情况与stdout也有缓冲区大小限制相同。

任何人都知道如何解决这个具体情况?

TL; DR:我需要一个“虚拟”文件,它将作为标准输出,但没有管道的标准尺寸限制。

3 个答案:

答案 0 :(得分:1)

有几种用于处理类似情况的工具:

  1. bufferpython app1 -o /dev/stdout | buffer | app2

  2. stdbufpython app1 -o /dev/stdout | stdbuf app2

  3. unbufferpython app1 -o /dev/stdout | unbuffer app2

  4. mbufferbuffer有更多选项):python app1 -o /dev/stdout | mbuffer | app2

  5. bash process substitutionpython app1 -o >(app2)

  6. utils有各种选项,其中一些可能是必需的(这取决于 app1 app2 正在做什么)。某些选项设置缓冲区的大小,或添加延迟,或显示诊断信息。

    Pixelbeat.org has some diagrams帮助可视化缓冲的工作原理(或未能)。

答案 1 :(得分:0)

您有几个选择:

  1. 使用文件。消费者不是从stdin读取,而是从文件中读取文件,并按照“tail -f”
  2. 中的代码实现文件
  3. 编写管道缓冲程序。这个选项有点愚蠢但是如果你不能改变其他任何一个都可以。我刚才在Perl写了一个,抱歉不能分享它,但基本上使用非阻塞IO从管道读取并写入管道,将所有数据保存在内存中。如果内存使用率太高,可能很难记录投诉。
  4. 修改阅读器或编写器以使用非阻塞IO并缓冲输出或输入。

答案 2 :(得分:0)

好。我的坏。

这不是缓冲问题,正如有些人在这里建议的那样。

这是一个CPU上限问题。这两个应用程序在运行时消耗100%的CPU和RAM,这就是应用程序崩溃的原因。