Потеря вывода из рубина при попытке ти (экран и файл) - PullRequest
0 голосов
/ 21 января 2012

У меня есть какой-то код, который я собрал из найденных подсказок, которые сработали. Но что-то идет не так, и я сбит с толку. На экран ничего не отправляется, а файл пуст.

Вот программа:

#!/usr/bin/env ruby -w

require "stringio"

class Tee

    def initialize
      date_str = `date '+%Y%m%d_%H%M%S'`.chomp
      @log = File.new("tee_output_example_#{date_str}.log","w")
    end

["$stdout", "$stderr"].each do |std|
   io           = eval(std)
   old_write    = io.method(:write)

   class << io
     self
   end.module_eval do
     define_method(:write) do |text|
       unless text =~ /^[\r\n]+$/       # Because puts calls twice.
         File.open(@log, "a") do |f|
#           f.puts [std[1..-1].upcase, caller[2], text].join(" ")
            f.puts text
         end
       end

       old_write.call(text)
     end
   end
 end
end

logger = Tee.new()

 logger.puts "text on stdout"
 logger.puts "Something else"

 $stdout = STDOUT
 $stderr = STDERR
 $stdout.puts "plain puts to $stdout"
 $stderr.puts "plain puts to $stderr"

Ответы [ 3 ]

2 голосов
/ 10 сентября 2012

Мне удалось решить это просто с помощью этой команды:

STDOUT.reopen IO.popen "tee stdout.log", "a"
STDERR.reopen IO.popen "tee stderr.log", "a"
0 голосов
/ 21 января 2012

Я мог бы дать несколько советов по методам отладки, но вместо этого я предложу альтернативное решение, которое может удовлетворить ваши потребности:

class Tee
  def initialize(a,b); @a,@b = a,b; end
  def method_missing(m,*args,&b)
    @a.send(m,*args,&b)
    @b.send(m,*args,&b)
  end
end

Этот класс более полезен, чем то, что вы пытались написать; он принимает 2 объекта и передает все вызовы методов (включая аргументы и блок) ОБА из них. Так что вы можете сделать что-то вроде:

tee = Tee.new(File.open("log","w"), $stdout)
tee.puts "Hello world AND log file!"
0 голосов
/ 21 января 2012

Ваши ожидания не очень ясны для меня, но это, кажется, разумное начало (с несколькими направлениями, которые вы можете предпринять, в зависимости от вашей конечной цели).

#!/usr/bin/env ruby -w

class Tee
  attr_accessor :log_file

  def initialize()
    self.log_file = File.open "tee_output_example_#{date_str}.log", "w"
    at_exit { log_file.close }
  end

  def date_str
    Time.now.strftime "%Y%m%d_%H%M%S"
  end

  def puts(*strings)
    log_file.puts(*strings)
    $stdout.puts(*strings)
  end
end

# will be sent to both $stdout and the logfile
logger = Tee.new
logger.puts "text on stdout"
logger.puts "Something else"

# will only be sent to $stdout or $stderr
$stdout.puts "plain puts to $stdout"
$stderr.puts "plain puts to $stderr"
...