【问题标题】:Using unbuffered pipe as "dummy" file output使用无缓冲管道作为“虚拟”文件输出
【发布时间】:2018-01-14 21:23:57
【问题描述】:

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

我的情况如下。

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

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

我想将“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

但情况与标准输出相同,也有缓冲区大小限制。

有人知道我该如何解决这个特定的场景吗?

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

【问题讨论】:

  • 听起来您遇到了需要解决的死锁问题。创建更大的管道并不是最好的解决方案。
  • 特别是,“管道将被填满,一切都将停止工作”的说法没有多大意义。如果管道填满,则 app1 将阻止写入,但 app2 应继续工作。当它从管道中清除数据时,app1 将开始写入更多数据。除非你有其他你没有描述的死锁。
  • 我的推断是因为如果我尝试使用缓冲管道,运行几个小时后,app2 将停止工作。如果我使用无缓冲管道(如 stderr),应用程序会持续运行数小时而不会出现问题。这是我(可能是错误的)扣除的唯一原因。

标签: linux bash pipe buffer stdout


【解决方案1】:

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

  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 &gt;(app2)

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

Pixelbeat.org has some diagrams 帮助可视化缓冲如何工作(或失败)。

【讨论】:

【解决方案2】:

你有几个选择:

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

【讨论】:

    【解决方案3】:

    嗯。我的错。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 2013-11-24
      相关资源
      最近更新 更多