【问题标题】:How can I capture Rake output when invoked from with a Ruby script?使用 Ruby 脚本调用时如何捕获 Rake 输出?
【发布时间】:2010-11-26 12:24:27
【问题描述】:

我正在为 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),有些似乎从未捕获输出(测试) .奇怪。

【问题讨论】:

    标签: ruby-on-rails rake stdout


    【解决方案1】:

    嗯,我知道 ZenTest 能够通过“until_capture”捕获“puts”语句,我什至发现有人通过扩展 Kernel 模块并将 $stdout 重定向到 StringIO 的实例来编写自定义实现。

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

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

    【讨论】:

    • 感谢您的建议。不幸的是,在内核模块中捕获 stdio 似乎与我使用本地 capture_output 方法得到的结果完全相同。
    【解决方案2】:

    虽然这是某种 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 中 rake 返回到标准输出的行。也许这更可靠,但我建议调查奇怪行为的来源 你描述的。

    【讨论】:

      【解决方案3】:

      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

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

      【讨论】:

        【解决方案4】:

        这对我有用:

        $stdout.reopen("my.log", "w")
        $stdout.sync = true
        
        # do your thing
        
        $stdout = STDOUT
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-27
          • 1970-01-01
          • 2012-10-18
          • 2011-01-05
          • 2021-11-27
          相关资源
          最近更新 更多