我正在为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),有些甚至没有捕获输出(测试) 。奇
答案 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