我正在使用Ruby编写一些脚本,并需要通过shell命令与一些非Ruby代码进行接口。我知道至少有6种不同的方法可以从Ruby执行shell命令,但不幸的是,这些方法似乎都不能在shell命令失败时停止执行。
基本上,我正在寻找做以下等效操作的东西:
set -o errexit
我希望能够在 Bash 脚本中执行命令并在命令执行失败时(即检查返回值是否为非零)引发异常,异常信息可以使用 stderr。虽然这不难实现,但似乎应该已经有现成的选项了。我是否错过了某些选项呢?
system('ctat nonexistent.txt', exception: true) # Errno::ENOENT (No such file or directory - ctat)
`ls`
if $? == 0
# Ok to go
else
# Not ok
end
最简单的方法是创建一个新函数(或重新定义现有函数)来调用system()并检查错误代码。
像这样:
old_sys = system
def system(...)
old_system(...)
if $? != 0 then raise :some_exception
end
raise
而不是 throw
。 - glenn jackman$?
的可读别名是 $CHILD_STATUS
。参考文献:https://docs.ruby-lang.org/en/2.2.0/Process/Status.html,https://ruby-doc.org/stdlib-2.5.0/libdoc/English/rdoc/English.html - Ben Amos$?
的值,只需要运行的命令会输出到 stderr
中,通常情况下,您只需使用非零退出即可,而不是引发带有丑陋堆栈跟踪的异常。system("<command>") || exit(1)
所以你可以再进一步,做到:
(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).
参考资料:从Ruby 2.0文档中的system
(虽然1.8.7也是如此):
如果命令返回零退出状态,则
system
返回true
,否则返回false
。
http://www.ruby-doc.org/core-2.0.0/Kernel.html#method-i-system
to_s
将$?
转换成字符串再与字符串0
比较?if $? == 0
- glenn jackman$?.zero?
抛出 NoMethodError。 - Mu-ik Jeon$?
从一开始就是nil
。 - Nakilonputs $?.class # Process::Status
该类没有 'zero?' 方法。 https://ruby-doc.org/core-2.2.0/Process/Status.html - Mu-ik Jeonif $?.success?
https://ruby-doc.org/core-2.2.0/Process/Status.html#method-i-success-3F。我使用的方式是exit $?.to_i unless $?.success?
。 - BvdBijl