通过 `myapp | myscript.rb` 将 stdin 管道传递给 Ruby 脚本

3

我有一个应用程序一直在运行,从服务器中不断地转储输出并将字符串发送到标准输出(stdout)。我想使用Ruby脚本处理这个输出,这些字符串以\n为终止。

例如,我试图在命令行上运行以下命令:

myapp.exe | my_script.rb

...其中my_script.rb定义如下:

while $stdin.gets
    puts $_
end

我最终将使用正则表达式处理字符串并显示一些摘要数据,但现在我只是试图让基本功能正常工作。当我运行上面的代码时,我会收到以下错误:

my_script.rb:1:in `gets': Bad file descriptor (Errno::EBADF)
        from my_script.rb:1

我正在运行Windows Server 2003 R2 SP2和Ruby 1.8.6。

如何在Ruby脚本中持续处理stdin?(持续处理指的是不处理文件,而是一直运行,直到我结束它。)

编辑:

我能够使这个工作,有点像。有几个问题阻碍着我。首先,使用Ruby处理来自另一个进程的管道输入的stdin可能在Windows 2003R2上无法正常工作。 Adrian提出的另一个方向是将我的脚本作为父进程运行,并使用popen将其连接到myapp.exe作为forked子进程。不幸的是,在Windows中没有实现fork,因此这也没有起作用。

最终我成功下载了 POpen4,这是一个在Windows上实现popen的RubyGem。结合Adrian的建议,我编写了这个脚本,它可以处理来自myapp.exe的输出:

文件:my_script.rb

require 'rubygems'
require 'popen4'

 status =
    POpen4::popen4("myapp.exe") do |stdout, stderr, stdin, pid|
        puts pid
        while s = stdout.gets
            puts s
        end

    end

这个脚本会回显myapp.exe的输出,这正是我想要的。

1
你试过不用管道运行Ruby脚本并输入一些内容来测试吗?你的代码在我的电脑上可以正常工作。 - Adrian
@Adrian:是的,我的脚本单独运行很好。它如预期和期望的那样回显我输入的一切。 - John Dibling
尝试使用普通的 gets,而不是 $stdin。如果这行不通,你可能需要用另一个 Ruby 脚本的 IO.popen 来检查 myapp.exe 的输出是否含有不可打印字符。 - Adrian
@Adrian:不幸的是,在Windows上fork无法工作,而popen使用了fork。有没有什么秘密咒语可以让它工作? - John Dibling
我能想到的唯一方法就是临时重写 myapp.exe 以在某个特定行数后退出,然后使用 %x - Adrian
@Adrian:我终于搞定了。虽然你的评论没有完全帮我解决问题,但是它指明了正确的方向。我会在帖子中编辑我使用的解决方案。如果你把popen的评论改成答案,我愿意接受它。 - John Dibling
3个回答

2
尝试使用纯粹的gets,不需要$stdin。如果这样做不起作用,您可能需要使用另一个ruby脚本通过IO.popen检查myapp.exe的输出中是否有非可打印字符。请注意保留HTML标签。

0

尝试通过显式调用ruby来执行您的Ruby脚本:

myapp.exe | ruby my_script.rb

在使用stdin时,我在Ruby中遇到了一些奇怪的行为,这是因为依赖Windows根据文件关联调用正确的程序。


0

gets 不总是使用 stdin,而是尝试打开一个文件。

请参见 SO


当我在代码中将$stdin替换为ARGF时,我仍然收到相同的错误。 我这样做对吗? - John Dibling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接