当使用 Ruby 脚本调用时,如何捕获 Rake 输出?
我正在为 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 源代码,但看不到它在哪里触发新进程或其他任何内容,所以我认为我应该能够做到这一点。
非常感谢! Adrian
我后来发现了从 Ruby 内部调用 Rake 的正确方法,效果更好:
Rake.application['db:migrate:redo'].reenable
Rake.application['db:migrate:redo'].invoke
奇怪的是,一些 rake 任务现在工作得很好(路由),有些在第一次运行时捕获输出,之后总是空白(db:migrate :重做),有些似乎从未捕获输出(测试)。奇怪的。
I am writing a web-based dev-console for Rails development. In one of my controller actions, I am calling Rake, but I am unable to capture any of the output that Rake generates. For example, here is some sample code, from the controller:
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
Does anybody know why I can't capture the Rake output? I've tried going through the Rake source, and I can't see where it fires a new process or anything, so I think I ought to be able to do this.
Many thanks!
Adrian
I have since discovered the correct way to call Rake from inside Ruby that works much better:
Rake.application['db:migrate:redo'].reenable
Rake.application['db:migrate:redo'].invoke
Strangely, some rake tasks work perfectly now (routes), some capture the output the first time the run and after that are always blank (db:migrate:redo) and some don't seem to ever capture output (test). Odd.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
虽然这是某种 hack(因为 Rack 是用 ruby 编写的),但您可以使用 open3 的 popen3 方法并像从命令行一样调用 rake 任务。
在你的情况下,你会像这样使用它,
所以你最终会得到所有在
buffer
中返回到 stdout 的行。也许这更可靠,但我建议调查奇怪行为的根源你描述。
While this is some kind of a hack (since Rack is written in ruby), you could use open3's popen3 method and invoke the rake task like you would from the commandline.
In your case you would use it like that
So you would end up with all lines that rake returned to stdout in
buffer
. Maybe this works more reliable, though I would recommend investigating the source of the odd behaviouryou describe.
嗯,我知道 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
Well, I know ZenTest is able to capture "puts"-statements through "until_capture" and I even found someone who wrote about a custom implementation by extending the Kernel module and redirecting $stdout to an instance of StringIO.
Hope that helps:
http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/
You may also want to check out OutputCatcher by Matthias Hennemeyer:
http://github.com/mhennemeyer/output_catcher
gems/rake-0.8.7/lib/rake.rb 第 1174 行:
也许尝试捕获 STDERR 以及 STDOUT?
我并不是说所有输出都是通过
$stderr
完成的,但 rake 本身似乎已经建立了该约定,也许在某个地方有人让某些 rake 任务覆盖了 put 以直接到$stderr
。我还没有测试过这个想法。
Line 1174 of gems/rake-0.8.7/lib/rake.rb:
Perhaps try capturing STDERR as well as STDOUT?
I'm not saying that all output is done through
$stderr
, but rake itself seems to have set up that convention, perhaps somewhere along the line someone made certain rake tasks overwrite puts to direct to$stderr
.I haven't tested the idea.
这对我有用:
参见:https://stackoverflow.com/a/2480439/21217
This does the trick for me:
Seen at: https://stackoverflow.com/a/2480439/21217