从Ruby运行shell命令:在显示输出时捕获输出?

我有个问题。

我想从另一个ruby脚本运行ruby脚本并捕获它的输出信息,同时让它输出到屏幕。

跑步者

#!/usr/bin/env ruby print "Enter your password: " password = gets.chomp puts "Here is your password: #{password}" 

我运行的脚本文件:

start.rb

 output = `runner` puts output.match(/Here is your (password: .*)/).captures[0].to_s 

如你所见,这是一个问题。

在start.rb的第一行,屏幕为空。

我在跑步者中看不到“输入你的密码:”。

有没有办法在它完成之前显示转轮脚本的输出,并且仍然让我将它捕获到一个字符串,以便我可以处理信息,例如。 在这个例子中使用匹配?

runner.rb

 STDOUT.print "Enter your password: " password = gets.chomp puts "Here is your password: #{password}" 

注意 STDOUT.print

start.rb

 require "stringio" buffer = StringIO.new $stdout = buffer require "runner" $stdout = STDOUT buffer.rewind puts buffer.read.match(/Here is your (password: .*)/).captures[0].to_s 

产量

 Enter your password: hello password: hello 

阅读更多…

我最近在这里写了一篇文章: 使用Ruby输出缓冲

试试这个:

 rd, wr = IO::pipe pid = Process.fork do $stdout.reopen(wr) rd.close exec("command") end wr.close rd.each do |line| puts "line from command: #{line}" end Process.wait(pid) 

类似的,如果你想捕获stderr 。 如果你需要捕获它们会更困难( Kernel.select ?)

编辑:一些解释。 这是一个古老的Unix程序:pipe + fork +调用dup2(重新打开),具体取决于你想要的。 简而言之:您创建一个管道作为孩子和父母之间的沟通方式。 在fork之后,每个对等体关闭它不使用的管道端点,子对象重新(重新打开)您需要的通道到管道的写端点,最后父对象读取管道的读取通道。

对于脚本无关的输出日志记录,您可能希望从终端仿真器(shell容器)启用它。 screen -L OR xterm -l这将捕获在模拟器中运行的任何shell或程序产生的所有输出,包括ruby脚本生成的输出。

您可以使用tee将内容写入文件或管道,然后读取文件。

看看POpen4 。 它声称是独立于平台的(但我不认为它适用于jruby,你可以使用IO#popen )。

让您的脚本将其提示输出到stderr。

 echo "Enter something" >&2 read answer echo "output that will be captured" 

如果您使用read -p发出提示,这将为您完成:

 read -p "Enter something" answer echo "output that will be captured" 
 io = IO.popen() log = io.readlines io.close 

现在在log变量中你有执行命令的输出。 解析它,转换它,或做任何你想做的事情。