3

我想知道如何$stdout在 ruby​​ 的线程环境中捕获输出。

一些细节。我将捕获用于记录目的,并且我必须sidekiq在后台处理作业,以便线程。我编码:

@previous_stdout, $stdout = $stdout, StringIO.new
self.stdout = $stdout.string

它抛出了我(对于某些线程):

WARN: undefined method `string' for #<IO:<STDOUT>>
4

1 回答 1

4

如果您自己记录事情,请为每个作业保留一个 StringIO 日志并写入它:

@log = StringIO.new
@log.write 'debug message'

Sidekiq 还提供日志记录选项:

https://github.com/mperham/sidekiq/wiki/Logging

否则你可以尝试一些真正的hacky,比如覆盖内核上的打印方法并同步它,这样你就不会意外地写入错误的$stdout。就像是:

require 'stringio'

module Kernel
  @@io_semaphore = Mutex.new

  [ :printf, :p, :print, :puts ].each do |io_write|
    hidden_io_write = "__#{io_write}__"

    alias_method hidden_io_write, io_write

    define_method(io_write) do |*args|
      @@io_semaphore.synchronize do
        $stdout = Thread.current[:log] || STDOUT
        self.__send__(hidden_io_write, *args)
        $stdout = STDOUT
      end
    end
  end
end

threads = 3.times.map do
  Thread.new do
    Thread.current[:log] = log = StringIO.new
    sleep(rand)
    puts "testing..."
    log.string
  end
end

logs = threads.map(&:value)
p logs
# => ["testing...\n", "testing...\n", "testing...\n"]
于 2013-04-24T05:52:03.383 回答