From: ara.t.howard@... Date: 2006-03-05T01:00:43+09:00 Subject: Re: Intercepting STDERR On Sat, 4 Mar 2006, Phrogz wrote: > Thanks so much, Ara. That's almost perfect, except that the exitstatus > seems to be eaten. No matter what happens, I get a clean 0 exitstatus. > For example: > > require 'open3' > > `lua xxx` > #=> lua: cannot open xxx: No such file or directory > > p $?.exitstatus > #=> 1 > > output, errors = '', '' > p Open3::popen3( "lua xxx" ){ |i,o,e| > i.close > o.each { |line| output << line } > e.each { |line| errors << line } > $?.exitstatus > } > #=> 0 > > > I can mostly infer the failure based on whether or not messages came to > stderr, but it'd be nice to know for sure. > > right you are. if you check out ruby-1.8.4/lib/open3.rb you'll see : ... pid = fork{ # child fork{ # grandchild ... ... ... } exit!(0) # check this out } ... so you'll never see an error. my open 4 package fixes this - i actually just made a release a few weeks ago to support throwing and exception when the exec fails. here's an example (it's on rubyforge): harp:~ > cat a.rb IO::popen("gem install open4 -r -y"){|pipe| pipe.read} and puts "installed open4..." require "rubygems" require "open4" def spawn cmd, opts = {} getopt = lambda{|o,*d| opts[o] || opts[o.to_s] || opts[o.to_s.intern] || d.shift} stdin = getopt["stdin"] || getopt[0, ""] stdout = getopt["stdout"] || getopt[1, ""] stderr = getopt["stderr"] || getopt[2, ""] Open4::popen4(cmd) do |cid,i,o,e| stdin.each{|line| i << line} i.close o.each{|line| stdout << line } e.each{|line| stderr << line } end [$?.exitstatus, stdout, stderr] end bt = lambda{|e| STDERR.puts %Q[#{ e.message } (#{ e.class })\n#{ e.backtrace.join "\n" }\n]} argvs = ["fubar"], ["ruby does-not-exist"], ["ruby", {"stdin" => "p 42"}] argvs.each do |argv| cmd, opts = argv puts puts "--- spawn( #{ cmd.inspect }, #{ opts.inspect } ) ---" p( spawn(*argv) ) rescue bt[$!] puts puts end harp:~ > ruby a.rb installed open4... --- spawn( "fubar", nil ) --- No such file or directory - fubar (Errno::ENOENT) /home/ahoward//lib/ruby/site_ruby/1.8/open4.rb:75:in `exec' /home/ahoward//lib/ruby/site_ruby/1.8/open4.rb:75:in `popen4' /home/ahoward//lib/ruby/site_ruby/1.8/open4.rb:57:in `popen4' a.rb:11:in `spawn' a.rb:36 a.rb:32 --- spawn( "ruby does-not-exist", nil ) --- [1, "", "ruby: No such file or directory -- does-not-exist (LoadError)\n"] --- spawn( "ruby", {"stdin"=>"p 42"} ) --- [0, "42\n", ""] hth. i'd sure like to get this in the stdlib... -a -- judge your success by what you had to give up in order to get it. - h.h. the 14th dali lama