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
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
···
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.
--
judge your success by what you had to give up in order to get it.
- h.h. the 14th dali lama