2

I'm shelling out of my Ruby script to call a system command as follows

puts "Reached point #1"

begin
  system("sh my_shell_script.sh")
rescue StandardError => e
  puts "There was an error"
end

puts "Reached point #2"

I purposely added an error in my shell script so it would fail (i.e. I spelled "echo" as "eho"). I would expect that my Ruby script would output that it reached marker #1, and then rescue the error to display "There was an error".

Instead, I'm getting:

"Reached point #1"
line 1: eho: command not found
"Reached point #2"

It certainly throws the correct error, but the shell error from system(...) isn't rescued. Any thoughts as to why?

user2490003
  • 10,706
  • 17
  • 79
  • 155
  • 1
    `system` won't raise an error. See http://stackoverflow.com/questions/2225305/raise-exception-on-shell-command-failure – Neil Slater Jun 16 '13 at 21:35

2 Answers2

5

From the documentation for Kernel#system:

system returns true if the command gives zero exit status, false for non zero exit status. Returns nil if command execution fails. An error status is available in $?.

This means that you have many ways to proceed (none of which involve rescuing a raised error), depending on exactly which failure information you want. If you just want to distinguish successfully executing the command with zero exit status from all forms of failure, this is the translation from your code:

puts "Reached point #1"

unless system("sh my_shell_script.sh")
  puts "There was an error"
end

puts "Reached point #2"

You can of course distinguish between command execution failure and non-zero exit status by looking at the return value, and you can get the exit status code from $? if needed, as per the documentation.

Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
  • 1
    One clarification: The terminal output says "line 1: eho: command not found", but the error retreived from $?.to_s says "pid 32303 exit 127". How do I access the actual terminal output instead of the status code? – user2490003 Jun 17 '13 at 00:00
  • @user2490003 You can't; it doesn't work that way. If you need the output of the command, use backticks (`\`sh my_shell_script.sh\``). That puts you back into using `begin`/`rescue`. – Darshan Rivka Whittle Jun 17 '13 at 00:07
1

Instead, I'm getting:

"Reached point #1"
line 1: eho: command not found
"Reached point #2"

So in other words, it got rescued, but not in the way that you're expecting.

What you actually want is probably more like this:

ret = system("sh my_shell_script.sh")
puts $? unless ret

http://www.ruby-doc.org/core-2.0/Kernel.html#method-i-system

Community
  • 1
  • 1
Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154