Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 线程安全:捕获$stdout的输出_Ruby_Multithreading_Debugging_Thread Safety_Sidekiq - Fatal编程技术网

Ruby 线程安全:捕获$stdout的输出

Ruby 线程安全:捕获$stdout的输出,ruby,multithreading,debugging,thread-safety,sidekiq,Ruby,Multithreading,Debugging,Thread Safety,Sidekiq,我想知道如何在ruby的线程环境中捕获$stdout的输出 一些细节。我使用捕获来记录日志,并且我有sidekiq来在后台处理作业,这样线程就可以运行了。Ive编码: @previous_stdout, $stdout = $stdout, StringIO.new self.stdout = $stdout.string 它让我(对于某些线程): 警告:未定义的方法'string'# 如果您自己记录事情,请为每个作业保留一个StringIO日志并写入: @log = StringIO.new

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

一些细节。我使用捕获来记录日志,并且我有
sidekiq
来在后台处理作业,这样线程就可以运行了。Ive编码:

@previous_stdout, $stdout = $stdout, StringIO.new
self.stdout = $stdout.string
它让我(对于某些线程):

警告:未定义的方法'string'#

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

@log = StringIO.new
@log.write 'debug message'
Sidekiq还提供日志记录选项:

否则,您可以尝试一些真正的黑客行为,比如覆盖内核上的打印方法并对其进行同步,这样您就不会意外地写入错误的$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"]

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

@log = StringIO.new
@log.write 'debug message'
Sidekiq还提供日志记录选项:

否则,您可以尝试一些真正的黑客行为,比如覆盖内核上的打印方法并对其进行同步,这样您就不会意外地写入错误的$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"]

你想为每一份工作制定不同的标准吗?首先。您的错误是当前的
$stdout
是一个普通的
IO
对象,而不是
StringIO
,因此它没有
string
方法。第二,在处理线程时不应该使用全局变量($stdout)。实际上,$stdout对于某些线程来说是一个StringIO,但不是所有线程,是的,显然是一个线程问题,我正在尝试为每个作业获取stdout。有什么想法吗?你想为每一份工作换一个不同的标准吗?首先。您的错误是当前的
$stdout
是一个普通的
IO
对象,而不是
StringIO
,因此它没有
string
方法。第二,在处理线程时不应该使用全局变量($stdout)。实际上,$stdout对于某些线程来说是一个StringIO,但不是所有线程,是的,显然是一个线程问题,我正在尝试为每个作业获取stdout。有什么想法吗?