【问题标题】:Ruby IO.popen STDOUT bufferingRuby IO.popen STDOUT 缓冲
【发布时间】:2011-10-30 07:59:17
【问题描述】:

我正在编写一个脚本,该脚本使用 IO.popen 打开另一个程序并不断读取数据。是这样的:

process = IO.popen(["/the/program", "argument", "argument"])

loop do
  line = process.gets
  puts "#{line}"
end

(显然,实际的程序不仅仅是打印输出 - 这只是一个示例。)

我遇到的问题是 popen 似乎正在从打开的进程中缓冲 STDOUT。我已经通过直接从 shell 并通过 popen 并排运行程序来证实这一点,而 Ruby 一次永远不会得到一行。它总是一次得到多行,并且有延迟。

我试过了

STDOUT.sync = true

...在popen之前,但这并没有改变任何东西。

有问题的程序肯定使用 \n 作为新行,所以这不是问题。

【问题讨论】:

  • 你试过process.sync = true吗?
  • @Eddie 你明白了吗?

标签: ruby popen


【解决方案1】:

你有其他程序的来源吗?您要么需要强制其他程序刷新其输出,要么让您的脚本看起来像一个 pty(参见 pty 标准库)。

请参阅this question,了解正在发生的事情。

编辑:pty示例代码:

require 'pty'
PTY.spawn "some-command" do |r,w,p|
  loop { puts r.gets }
end

【讨论】:

  • 如果最后一行没有以换行符结尾(例如,如果某些命令是 echo -n ABC),则无法打印最后一行。
【解决方案2】:

我怀疑/the/program 在检测到 stdout 不是终端时正在缓冲 - 您可以通过 cat 管道进行测试,例如:

"/the/program" "argument" "argument" | cat

上面的答案,如果是问题就解决它,即:

#!/usr/bin/env ruby

require 'pty'
PTY.spawn "./the-program testing one Two three" do |r,w,p|
  loop { puts "GOT: #{r.gets}" }  
end

某些语言(例如 C)检测 stdout 是否为终端并更改为行缓冲 - 请参阅 Is stdout line buffered, unbuffered or indeterminate by default?

作为一个例子,我使用了一个简单的 bash 脚本来输出每个参数和时间,一次一个,中间间隔 3 秒,并且 ruby​​ 脚本可以正常工作。我为这个例子添加了 eof 检测。

修改后的脚本:

#!/usr/bin/env ruby

process = IO.popen(["./the-program", "testing", "one", "Two", "three"])

while !process.eof?
  line = process.gets
  puts "GOT: #{line}"
end

节目内容:

#!/bin/bash

for arg
do
  echo $arg
  date
  sleep 3
done

我尝试使用 ruby​​ 版本 1.9.3 和 2.1.2

$ ruby ,p
GOT: testing
GOT: Mon Jun 16 06:19:00 EST 2014
GOT: one
GOT: Mon Jun 16 06:19:03 EST 2014
GOT: Two
GOT: Mon Jun 16 06:19:06 EST 2014
GOT: three
GOT: Mon Jun 16 06:19:09 EST 2014
$ 

如果我改用 C 程序,那么问题再次出现:

#include <stdio.h>

main(int argc, char **argv)
{
        int i;

        for (i=0; i<argc; i++) {
                printf("%s\n", argv[i]);
                sleep(3);
        }
}

【讨论】:

    猜你喜欢
    • 2020-04-12
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多