I'm writing some scripts in Ruby, and I need to interface with some non-Ruby code via shell commands. I know there are at least 6 different ways of executing shell commands from Ruby, unfortunately, none of these seem to stop execution when a shell command fails.
Basically, I'm looking for something that does the equivalent of:
set -o errexit
...in a Bash script. Ideally, the solution would raise an exception when the command fails (i.e., by checking for a non-zero return value), maybe with stderr as a message. This wouldn't be too hard to write, but it seems like this should exist already. Is there an option that I'm just not finding?
Easiest way would be to create a new function (or redefine an existing one) to call system() and check the error code.
Something like:
old_sys = system
def system(...)
old_system(...)
if $? != 0 then raise :some_exception
end
This should do what you want.
You can use one of ruby's special variables. The $? (analogous to the same shell script var).
`ls`
if $?.to_s == "0"
# Ok to go
else
# Not ok
end
Almost every program sets this var to 0 if everything went fine.
Tiny bit simpler: you don't need to check $?
w/ system
, and since the command you ran will output to stderr
itself you can usually just non-zero-exit rather than raising an exception w/ an ugly stack-trace:
system("<command>") || exit(1)
So you could take that a step further and do:
(system("<command 1>") &&
system("<command 2>") &&
system("<command 3>")) || exit(1)
...which would short-circuit and fail on error (in addition to being hard to read).
Ref: From Ruby 2.0 doc for system
(although true of 1.8.7 as well):
system returns true
if the command gives zero exit status, false
for non zero exit status.
http://www.ruby-doc.org/core-2.0.0/Kernel.html#method-i-system
Ruby 2.6 adds an exception:
argument:
system('ctat nonexistent.txt', exception: true) # Errno::ENOENT (No such file or directory - ctat)