2012-01-21 3 views
0

私はヒントが見つかったので、私が一緒に手錠をかけたコードを手に入れました。しかし、何かが間違っている、と私はうんざりしています。何も画面に送られず、ファイルは空です。tee(画面とファイル)をしようとしているときにルビーの出力が失われる

#!/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" 
+0

そこに質問はありますか? –

+0

あなたはどのバージョンのRubyをお使いですか? –

+0

受け入れテストは何ですか?例えばあなたはファイルとstdoutで何を見たいですか? –

答えて

0

あなたの期待が私には非常に明確ではありませんが、これは(いくつかの方向で、あなたの究極の目標に応じて、それを取ることができる)合理的なスタートのようです:

は、ここでプログラムです。

#!/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" 
+0

私は解決策を提供していただき、ありがとうございます。その目的は、画面とファイルの両方に簡潔に出力することです。 –

0

私はデバッグ手法についていくつかのヒントを与えることができるが、その代わりに、私はあなたのニーズを満たす可能性がある代替ソリューションを提案します:

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!" 
2

:だからあなたのような何かを行うことができ

STDOUT.reopen IO.popen "tee stdout.log", "a" 
STDERR.reopen IO.popen "tee stderr.log", "a" 
+0

うわー、素敵な簡単な解決策。私は意図していない副作用が1つあると思う。両方のログファイルでstderr出力が終了するように見えます。おそらく、** teeコマンド自体**がstdoutに出力され、stdoutがstdout.logにリダイレクトされたためです。例: プット 'STDOUT' STDERR.puts 'stderrの' たSTDERR.log: stderrの あるstdout.log: STDOUT 標準エラー出力 –

関連する問題