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

时间:2010-09-10 07:16:59

标签: ruby bash

我有一个问题。

我想从另一个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的第一行,屏幕为空。

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

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

7 个答案:

答案 0 :(得分:7)

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

了解更多......

我最近在这里写了一篇文章:Output Buffering with Ruby

答案 1 :(得分:2)

试试这个:

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之后,每个对等体关闭它不使用的管道端点,子对象重新(重新打开)您需要的通道到管道的写端点,最后父对象读取管道的读取通道。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

看看POpen4。 它声称与平台无关(但我不认为它适用于jruby,你可以使用IO#popen)。

答案 5 :(得分:0)

让您的脚本将其提示输出到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"

答案 6 :(得分:0)

io = IO.popen(<your command here>)
log = io.readlines
io.close

现在在日志变量中,您拥有已执行命令的输出。解析它,转换它,或做任何你想做的事。