From: Simon Strandgaard <0bz63fz3m1qt3001@...> Date: 2003-05-07T09:33:50+09:00 Subject: Re: capture output On Wed, 07 May 2003 09:33:31 +0900, Florian G. Pflug wrote: > On Wed, May 07, 2003 at 07:53:05AM +0900, Simon Strandgaard wrote: >> I want to capture all output from [ruby, child_processes]. >> How can I do this ? > You need to use $stdout.reopen(buf) here. Same for $stderr. > > But since IO::reopen seems to be a quite special function (it actually > _replaces_ its receiver - it's the only ruby function I know of that does > this), it might be that the argument has to be of a special class (maybe > derived from IO?). Yes.. The problem is *almost* solved - I found this (thanks paul brannan): http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=20020807095619.D4512%40atdesk.com&rnum=12&prev=/groups%3Fq%3Druby%2Bstringio%26hl%3Den%26lr%3D%26ie%3DUTF-8%26start%3D10%26sa%3DN There seems to be some glitches where it does'nt capture all output. I get 2 different kinds of output.. here is the first output: > ruby main.rb OK 1 OK stderrstdout OK defout OK OK 2 OK stderr OK stdout OK defout OK 3 > The line "OK stderrstdout" is buggy.. The second output: > ruby main.rb OK 1 OK stderr OK stdout OK defout OK 2 OK stderr OK stdout OK defout OK 3 > Running the code several times, then you will see that it varies between first&second output.. Why ??? > cat main.rb require 'stringio' class Redirector def initialize(from, to) tmp = from.dup r, w = IO.pipe from.reopen(w) @t = Thread.new do begin loop do s = r.read(1) # TODO: can I make this buffered? to.write(s) end ensure from.reopen(tmp) end end end def stop @t.kill end def self.redirect(from, to) s = self.new(from, to) begin yield ensure s.stop end end end def capture raise unless block_given? a, b, c = $defout, $stderr, $stdout buf = StringIO.new(s = "", "w") rdr_serr = Redirector.new($stderr, buf) rdr_sout = Redirector.new($stdout, buf) begin $defout = buf yield ensure $defout, $stderr, $stdout = a, b, c rdr_serr.stop rdr_sout.stop buf.close end s.split(/\n/) end res = capture { puts "1" system("ruby output.rb") puts "2" puts `ruby output.rb` puts "3" } puts res.collect{|s| "OK "+s }.join("\n") > cat output.rb $stderr.puts "stderr" $stdout.puts "stdout" $defout.puts "defout" > The remaining question: Why does the output differs when I run the program several times ??? -- Simon Strandgaard