使用Ruby脚本调用时如何捕获Rake输出?

时间:2009-09-08 13:39:15

标签: ruby-on-rails rake stdout

我正在为Rails开发编写一个基于Web的开发控制台。在我的一个控制器动作中,我正在调用Rake,但是我无法捕获Rake生成的任何输出。例如,以下是来自控制器的一些示例代码:

require 'rake'
require 'rake/rdoctask'
require 'rake/testtask'
require 'tasks/rails'
require 'stringio'

...

def show_routes

  @results = capture_stdout { Rake.tasks['routes'].invoke }

  # @results is nil -- the capture_stdout doesn't catpure anything that Rake generates

end

def capture_stdout
  s = StringIO.new
  $stdout = s
  yield
  s.string
ensure
  $stdout = STDOUT
end

有人知道为什么我无法捕获Rake输出吗?我试过通过Rake源代码,我无法看到它在哪里触发新进程或任何东西,所以我认为我应该能够做到这一点。

非常感谢! 阿德里安


我已经发现从Ruby内部调用Rake的正确方法更好:

Rake.application['db:migrate:redo'].reenable
Rake.application['db:migrate:redo'].invoke

奇怪的是,一些rake任务现在完美地工作(路由),一些在第一次运行时捕获输出,之后总是空白(db:migrate:redo),有些甚至没有捕获输出(测试) 。奇

4 个答案:

答案 0 :(得分:3)

虽然这是某种黑客行为(因为Rack是用ruby编写的),你可以使用open3的popen3方法并像命令行那样调用rake任务。

在你的情况下你会像那样使用它

require 'open3'

buffer = []
Open3::popen3("rake db:migrate:redo") do |stdin,stdout,stderr|
  begin
    while line = stdout.readline
      buffer << line
    end
  rescue
  end
end

所以你最终会得到所有rake返回到buffer中的stdout的行。也许这会更可靠,但我建议调查奇怪行为的来源  你形容。

答案 1 :(得分:2)

嗯,我知道ZenTest能够通过“until_capture”捕获“puts” - 语句,我甚至找到了一个通过扩展内核模块并将$ stdout重定向到StringIO实例来编写自定义实现的人。

希望有所帮助:
http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/

您可能还想查看Matthias Hennemeyer撰写的OutputCatcher:
http://github.com/mhennemeyer/output_catcher

答案 2 :(得分:1)

第1174行gems / rake-0.8.7 / lib / rake.rb:

  # Send the message to the default rake output (which is $stderr).
  def rake_output_message(message)
    $stderr.puts(message)
  end
  private :rake_output_message

也许尝试捕获STDERR以及STDOUT?

我并不是说所有的输出都是通过$stderr来完成的,但是rake本身似乎已经设置了这个约定,也许某个地方有人让某些rake任务覆盖了直接转到{{1} }。

我没有测试过这个想法。

答案 3 :(得分:1)

这对我有用:

$stdout.reopen("my.log", "w")
$stdout.sync = true

# do your thing

$stdout = STDOUT

见:https://stackoverflow.com/a/2480439/21217