我想知道如何在 ruby 的线程环境中捕获 $stdout
的输出。
一些细节。我将捕获用于日志记录目的,并且我有 sidekiq
在后台处理作业,因此线程。我编码:
@previous_stdout, $stdout = $stdout, StringIO.new
self.stdout = $stdout.string
它抛出我(对于某些线程):
WARN: undefined method `string' for #<IO:<STDOUT>>
最佳答案
如果您自己记录事情,请为每个作业保留一个 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"]
关于ruby - 线程安全 : Capturing the output of $stdout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16183177/