Reputation: 29
I've got some code that I cobbled together from hints found that worked. But something is going wrong, and I am baffled. Nothing is sent to the screen, and file is empty.
Here's the program:
#!/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"
Upvotes: 0
Views: 1006
Reputation: 29450
I managed to solve it simply with this command:
STDOUT.reopen IO.popen "tee stdout.log", "a"
STDERR.reopen IO.popen "tee stderr.log", "a"
Upvotes: 3
Reputation: 30465
I could give some tips on debugging techniques, but instead, I'll suggest an alternate solution which might meet your needs:
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
This class is more generally useful than what you were trying to write; it takes 2 objects, and passes all method calls (including arguments and block) on to BOTH of them. So you could do something like:
tee = Tee.new(File.open("log","w"), $stdout)
tee.puts "Hello world AND log file!"
Upvotes: 0
Reputation: 31756
Your expectations aren't very clear to me, but this seems to be a reasonable start (with several directions you could take it depending on your ultimate goal).
#!/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"
Upvotes: 0