7

Is there a way to capture a "command not found" error in a Ruby script? For instance, given:

output = `foo`

How do I trap the situation where foo isn't installed? I expected that I could rescue an exception, but this doesn't seem to work on 1.8.7. Is there a different way of calling the subprocess that will do what I want? Or is there a different approach?

Update

My apologies, I forgot to mention a hidden requirement: I would prefer that the interpreter doesn't leak the command line to the user (it can contain sensitive data), hence why the exception catching method is preferred. Apologies again for leaving this out the first time.

kfb
  • 6,252
  • 6
  • 40
  • 51
  • One tactic that is useful when you need a specific feature, is to run a preflight-check, looking for the feature, or app, or code first, before trying to run it. Saying `which 'foo'` or using a couple File tests to look for the existence of the file plus its executability, will tell you whether it is safe to proceed without actually attempting the command and failing. It makes for a better user experience because you can control how you react to the missing functionality, and either go an alternate route, or notify the user you can't proceed because something is missing. – the Tin Man Jan 25 '11 at 02:11
  • Agreed, but `which 'foo'` isn't cross-platform, and I couldn't think of a cross-platform way to do it other than to try it and catch the error... – kfb Jan 25 '11 at 14:15

1 Answers1

14

Use the return code!

irb(main):001:0> `date`
=> "Mo 24. Jan 16:07:15 CET 2011\n"
irb(main):002:0> $?
=> #<Process::Status: pid=11556,exited(0)>
irb(main):003:0> $?.to_i
=> 0
irb(main):004:0> `foo`
(irb):4: command not found: foo
=> ""
irb(main):005:0> $?.to_i
=> 32512

http://corelib.rubyonrails.org/classes/Process/Status.html

Redirecting STDERR to STDOUT will give you the output as return value instead of bloating it just out:

irb(main):010:0> `foo 2>&1`
=> "sh: foo: not found\n"
irb(main):011:0> $?.to_i
=> 32512
Lennart Koopmann
  • 826
  • 1
  • 8
  • 14
  • Thanks! However I forgot to mention an extra requirement of not leaking the command line back out; if I understand correctly this would still show the command not found message to the user. – kfb Jan 24 '11 at 15:39
  • Added example on how to do this to my answer. – Lennart Koopmann Jan 24 '11 at 15:44
  • I know this is an oldie but $?.exitstatus is a much more transparent (readable) way of getting the exit code. – Mike Kelly Jul 22 '22 at 15:13