使用无缓冲管道作为 "dummy" 文件输出

Using unbuffered pipe as "dummy" file output

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

我的情况如下

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

我有一个辅助应用程序,名为 "app2";一个二进制文件,从 stdin.

获取 输入

我想将 "app1" 生成的内容直接通过管道传输到 "app2" 进行处理,理想情况下应该是这样的:

app1 | app2

但是,正如我所说,有一些限制,例如 app1 需要一个文件 作为输出。 我为 "fooling" 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: 我需要一个 "dummy" 文件作为标准输出,但没有管道的标准大小限制。

您有几个选择:

  1. 使用文件。让消费者从文件中读取并按照 "tail -f"
  2. 中的代码实现文件,而不是从标准输入读取
  3. 编写一个管道缓冲程序。这个选项有点傻,但如果你不能改变其他任何一个,它就可以工作。前段时间我用Perl写了一个,抱歉不能分享,但是基本上是使用非阻塞IO从管道读取和写入管道,将所有数据保存在内存中。如果内存使用率过高,记录投诉可能很好。
  4. 修改 reader 或编写器以使用非阻塞 IO 并缓冲输出或输入。

有几个实用程序旨在处理类似情况:

  1. buffer: python app1 -o /dev/stdout | buffer | app2

  2. stdbuf: python app1 -o /dev/stdout | stdbuf app2

  3. unbuffer: python app1 -o /dev/stdout | unbuffer app2

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

  5. bash process substitution: python app1 -o >(app2)

实用程序有各种选项,其中一些可能在这里需要,(这取决于 app1app2 在做什么) .一些选项设置缓冲区的大小,或添加延迟,或显示诊断信息。

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

嗯。我的错。

这不是缓冲区问题,正如某些人在此处建议的那样。

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