打开管道的缓冲问题,写入文件

Posted

技术标签:

【中文标题】打开管道的缓冲问题,写入文件【英文标题】:Buffering issue on Open pipe, write to file 【发布时间】:2020-05-29 13:54:17 【问题描述】:

我有一个脚本,可以打开一个启动外部程序的进程。外部程序写入标准输出,在父程序中我同时写入标准输出和文件。立即打印到标准输出,但打印到文件正在缓冲。在将其转储到文件之前,它必须等待某种 Xk 编号。我已经在输出文件、管道、stdout 上尝试了 autoflush,并且还使用了 stdbuf。但是没有任何作用,因为它只以块消息的形式写入文件。我错过了什么吗?

      my $output = "/home/output.log";
      open(OL,">$output");
      OL->autoflush(1);
      open(P,'-|',"stdbuf -o0 -e0 external_program.py 2>&1");
      $| = 1;
      P->autoflush(1);
      STDOUT->autoflush(1);
      while(<P>) 
        chomp;
        print OL "$_\n";
        print "$_\n";
      
      close(OL);
      close(P);

【问题讨论】:

【参考方案1】:

我不确定为什么stdbuf 不起作用,但您可以使用 unbuffer 命令。这是一个简单的例子:

use feature qw(say);
use strict;
use warnings;
my $output = "output.log";
open(my $OL,">", $output) or die "Could not open file '$output': $!";
my $pid = open (my $P, '-|', "unbuffer test.pl 2>&1");
while(<$P>) 
    chomp;
    print $OL "$_\n";
    print "$_\n";

close $OL;
close $P;

其中test.pl 给出为:

#! /usr/bin/env perl
use strict;
use warnings;
for (1..5) 
    print "Hello\n";
    sleep 1;

你可以使用sudo apt-get install expect在Ubuntu上安装unbuffer命令

如果在上面的脚本中没有unbuffer 命令,所有带有Hello 的五行将在终端窗口5 秒后立即打印。使用unbuffer 命令时,每秒会出现一个带有Hello 的新行。

更新

既然你的脚本被命名为external_program.py 我假设它是一个python 程序?然后python 有一个-u 命令行选项可以关闭缓冲,您可以使用此选项而不是运行unbuffer

【讨论】:

是的,它是一个 python 脚本,我已经运行了 -u 选项。 您是否删除了stdbuf 命令?试试open(P,'-|',"python -u external_program.py 2&gt;&amp;1"); 还是output.log 没有更新?【参考方案2】:

Hakon,我确实已经运行了“python3.6 -u external_program.py”。我终于找到了有用的东西。如果我将打印更改为文件以在每次写入一行时刷新,那么它可以工作

所以我替换以下内容:

    OL "$_\n";<br>
    with
    OL->printflush("$_\n");

【讨论】:

这并没有做任何OL-&gt;autoflush(1); 还没有做的事情。 OL-&gt;printflush("$_\n"); 打印、设置自动刷新,然后恢复之前的自动刷新设置。 我想明确一点,我用 OL->printflush 替换了 while 循环内的打印。如果与 OL->autoflush 没有区别,这是否意味着我也应该将其放在 while 循环中?

以上是关于打开管道的缓冲问题,写入文件的主要内容,如果未能解决你的问题,请参考以下文章

我需要刷新命名管道吗?

Go-文件目录操作分类详解(创建打开关闭读取写入判断等)

文件系统中的命名管道不是很慢吗?

将NodeJS流消耗到缓冲区并写入流的正确方法

Linux-C:从管道读取返回写入它的第一个缓冲区

如果管道已满,写入管道的进程是不是会阻塞?