Perl中的行缓冲读取

时间:2014-02-22 15:55:36

标签: perl unix

我有一个perl脚本,说“process_output.pl”,用于以下语境:

  

long_running_command | “process_output.pl”

process_output脚本需要像unix“tee”命令一样,它在生成时将“long_running_command”的输出转储到终端,另外还将输出捕获到文本文件,并在“long_running_command”结束时“,以文本文件作为输入分叉另一个进程。

我目前看到的行为是,“long_running_command”的输出被转储到终端,只有当它完成而不是在生成时转储输出。我需要做一些特别的事来解决这个问题吗?

根据我在其他一些stackexchange帖子中的阅读,我在“process_output.pl”中尝试了以下内容,没有太多帮助:

  1. select(STDOUT); $| =1;
  2. select(STDIN); $| =1; # Not sure even if this is needed
  3. use FileHandle; STDOUT->autoflush(1);
  4. stdbuf -oL -eL long_running_command | "process_output.pl"
  5. 关于如何进一步行动的任何指示。

    由于 AB

2 个答案:

答案 0 :(得分:4)

这更有可能是缓冲的第一个进程的输出的问题,而不是脚本的输入。最简单的解决方案是尝试使用unbuffer命令(我相信它是expect包的一部分),类似

unbuffer long_running_command | "process_output.pl"

unbuffer命令将禁用当输出定向到非交互位置时正常发生的缓冲。

答案 1 :(得分:1)

这将是long_running_processing的输出处理。很可能它正在使用stdio - 它将查看输出文件描述符在输出之前连接的内容。如果它是一个终端(tty),那么它通常会输出基于行的,但在上面的情况下 - 它会注意到它正在写入管道,因此会将输出缓冲到更大的块中。

您可以使用,如您所示

,在您自己的过程中控制缓冲
select(STDOUT); $| =1;

这意味着你的进程打印到STDIO的东西没有被缓冲 - 为输入做这个是没有意义的,因为你控制了多少缓冲 - 如果你使用sysread()那么你正在读取无缓冲,如果你使用像<$fh>这样的结构,那么perl会等到它有一个“整行”(它实际读取到下一个输入行分隔符(在变量$/中定义,默认为换行符) )在它向你返回数据之前。

unbuffer可以用来“禁用”输出缓冲,它实际上做的是让输出过程认为它正在与tty通话(通过使用伪tty)所以输出过程没有缓冲。