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

发布于 2024-08-03 17:50:50 字数 873 浏览 7 评论 0原文

我正在为 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深海少女心 2024-08-10 17:50:50

虽然这是某种 hack(因为 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

所以你最终会得到所有在 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

require 'open3'

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

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 behaviour
you describe.

墨离汐 2024-08-10 17:50:50

嗯,我知道 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

妖妓 2024-08-10 17:50:50

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

  # 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 任务覆盖了 put 以直接到 $stderr

我还没有测试过这个想法。

Line 1174 of 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

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.

爱的那么颓废 2024-08-10 17:50:50

这对我有用:

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

# do your thing

$stdout = STDOUT

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

This does the trick for me:

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

# do your thing

$stdout = STDOUT

Seen at: https://stackoverflow.com/a/2480439/21217

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文