3

目前,我有:

$stdout.sync = true
$stderr.sync = true
orig_stdout = $stdout.clone
orig_stderr = $stderr.clone
$stdout.reopen("log.txt","w")
$stderr.reopen("log.txt","w")

#Run some processes that I want to hide from user view

$stdout.reopen(orig_stdout)
$stderr.reopen(orig_stderr)

#Display feedback on processes completing and continue with Ruby program. 
end

但是,当我运行它时,Ruby 不会将 stdout 和 stderr 发送回终端。直到程序进程被杀死,它们才会被显示,然后它们会显示在终端上。

有没有办法立即将 stdout 和 stderr 交换回终端?谢谢

编辑:

在#Run 一些我想从用户视图中隐藏的进程中,我还需要在这些进程中用户输入 svn 用户名和 svn 密码。这就是程序不会输出回终端的原因。

我仍然需要能够将所有输出重定向到“log.txt”文件并再次返回,但需要实现 svn。

4

1 回答 1

0

这是一个老问题,我发现自己处于同样的境地。我编写了一个扩展和File覆盖方法的 Multi-IO 类,我还确保了它的线程安全:write putsclose

require 'singleton'

class MultiIO < File
  include Singleton 
  @@targets = []
  @@mutex = Mutex.new

  def self.instance
    self.open('/dev/null','w+')
  end

  def puts(str)
    write "#{str}\n"
  end

  def write(str)
    @@mutex.synchronize do 
      @@targets.each { |t| t.write str; flush }
    end
  end

  def setTargets(targets)
    raise 'setTargets is a one-off operation' unless @@targets.length < 1
    targets.each do |t|
       @@targets.push STDOUT.clone if t == STDOUT 
       @@targets.push STDERR.clone if t == STDERR
       break if t == STDOUT or t == STDERR  
       @@targets.push(File.open(t,'w+'))
    end
    self
  end

  def close
    @@targets.each {|t| f.close}
  end
end

STDOUT.reopen MultiIO.instance.setTargets(['/tmp/1.log',STDOUT,STDERR])
STDERR.reopen STDOUT 


threads = []

5.times.each do |i| 
  threads.push( 
    Thread.new do
      10000.times.each do |j|
        STDOUT.puts "out#{i}:#{j}"
      end
    end
  )
end

5.times.each do |i| 
  threads.push( 
    Thread.new do
      10000.times.each do |j|
        STDERR.puts "err#{i}:#{j}"
      end
    end
  )
end

threads.each {|t| t.join}
于 2017-10-18T19:09:28.287 回答