From: Damphyr Date: 2005-12-09T06:58:48+09:00 Subject: Re: getting stdout and stderr for system calls on windows I ended up with the following after this discussion. It doesn't separate stderr and stdout, but for what I want it, it's more than enough. And I added crude benchmarking as well:) : There was also an exitcode method in there (you can get the exitcde from @process). #Executes a command on a dos shell, redirecting stderr to stdout ("2>&1") # #You can then access the output and the return value for the command. # #This is meant as a last-resort replacement for popen3 (because of problems with VC++6.0 and the Ruby One-Click Installer). # #_exec_time_ provides the Time spent running the command. class ExecCmd attr_reader :output,:cmd,:exec_time #When a block is given, the command runs before yielding def initialize cmd @output="" @exec_time=0 @cmd=cmd @cmd_run=cmd+" 2>&1" unless cmd=~/2>&1/ if block_given? run yield self end end #Runs the command def run t1=Time.now IO.popen(@cmd_run){|f| @output=f.read @process=Process.waitpid2(f.pid)[1] } @exec_time=Time.now-t1 end #Returns false if the command hasn't been executed yet def run? return false unless @process return true end #Returns true if the command was succesfull. # #Will return false if the command hasn't been executed def success? return @process.success? if @process return false end end www-data wrote: > I have the same problem, and i'm likely going to end up using this > syntax inside a system call: > > (((dmake target | tee stdout.txt) 3>&1 1>&2 2>&3 | tee stderr.txt) 3>&1 > 1>&2 2>&3) 2>&1 | tee output.txt > > where output.txt will contain stderr + stdout > stdout.txt will contain stdout > stderr.txt will contain stderr > > There is a description of how this works here: > http://www.cpqlinux.com/redirect.html > Scroll down to "Capturing stderr with tee Swapping stderr and stdout" > Ugly as hell but it does the trick... hopefully someone knows a cleaner > way to do this within ruby? > > -- > > ara.t.howard wrote: > >>On Thu, 24 Nov 2005, Damphyr wrote: >> >> >>>system 'echo blabla' >>>stdout. >>> >>>Cheers, >>>V.- >> >>i was working on this at one point: >> >> harp:~ > cat a.rb >> class Redirector >> require "tempfile" >> attr_accessor "ruby" >> def initialize >> @ruby = "ruby" >> @script = tempfile >> @script.write <<-ruby >> stdout, stderr = ARGV.shift, ARGV.shift >> File::unlink out rescue nil >> File::unlink err rescue nil >> STDOUT.reopen(open(stdout,"w")) >> STDERR.reopen(open(stderr,"w")) >> system(ARGV.join(' ')) >> ruby >> @script.close >> end >> def run command, redirects = {} >> stdout = redirects.values_at("stdout", :stdout, "o", :o, >>1).compact.first >> tout = nil >> unless stdout >> tout = tempfile >> stdout = tout.path >> end >> stderr = redirects.values_at("stderr", :stderr, "e", :e, >>2).compact.first >> terr = nil >> unless stderr >> terr = tempfile >> stderr = terr.path >> end >> system "#{ @ruby } #{ @script.path } #{ stdout } #{ stderr } #{ >>command }" >> ret = IO::read(stdout), IO::read(stderr), $?.exitstatus >> tout.close! if tout >> terr.close! if terr >> ret >> end >> def tempfile >> Tempfile::new(Process::pid.to_s << rand.to_s) >> end >> end >> >> redirector = Redirector::new >> >> stdout, stderr, exitstatus = redirector.run "echo 42" >> p [stdout, stderr, exitstatus] >> >> redirector.run "echo 42", 1 => "out", 2 => "err" >> p [IO::read("out"), IO::read("err")] >> >> >> harp:~ > ruby a.rb >> ["42\n", "", 0] >> ["42\n", ""] >> >>regards. >> >>-a > > > -- http://www.braveworld.net/riva ____________________________________________________________________ http://www.freemail.gr - ������ �������� ������������ ������������. http://www.freemail.gr - free email service for the Greek-speaking.