将stderr和stdout重定向回终端?

时间:2012-08-20 18:16:00

标签: ruby

目前,我有:

$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。

1 个答案:

答案 0 :(得分:0)

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

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}