【问题标题】:Raise exception on shell command failure?在 shell 命令失败时引发异常?
【发布时间】:2011-01-14 13:57:43
【问题描述】:

我正在用 Ruby 编写一些脚本,我需要通过 shell 命令与一些非 Ruby 代码交互。我知道至少有 6 different ways 从 Ruby 执行 shell 命令,不幸的是,当 shell 命令失败时,这些似乎都不会停止执行。

基本上,我正在寻找的东西相当于:

set -o errexit

...在 Bash 脚本中。理想情况下,解决方案会在命令失败时引发异常(即通过检查非零返回值),可能会使用 stderr 作为消息。这不会太难写,但它似乎应该已经存在。有没有我找不到的选项?

【问题讨论】:

    标签: ruby exception shell


    【解决方案1】:

    您可以使用 ruby​​ 的特殊变量之一。美元? (类似于相同的 shell 脚本 var)。

    `ls`
    if $?.to_s == "0"
      # Ok to go
    else
      # Not ok
    end
    

    如果一切正常,几乎每个程序都会将此 var 设置为 0。

    【讨论】:

    【解决方案2】:

    最简单的方法是创建一个新函数(或重新定义一个现有函数)来调用 system() 并检查错误代码。

    类似:

    old_sys = system
    
    def system(...)
      old_system(...)
      if $? != 0 then raise :some_exception
    end
    

    这应该做你想做的。

    【讨论】:

    【解决方案3】:

    稍微简单一点:您不需要检查$? w/system,并且由于您运行的命令将输出到stderr 本身,您通常可以只非零退出而不是引发异常带有丑陋的堆栈跟踪:

    system("<command>") || exit(1)
    

    所以你可以更进一步做:

    (system("<command 1>") &&
      system("<command 2>") &&
      system("<command 3>")) || exit(1)
    

    ...它会短路并因错误而失败(除了难以阅读)。

    参考:来自 system 的 Ruby 2.0 文档(尽管 1.8.7 也是如此):

    如果命令给出零退出状态,则系统返回true,对于非零退出状态返回false

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

    【讨论】:

    • 有趣,我喜欢这个。您能否添加指向您的参考资料的链接(您在 Ruby 文档中找到此内容的部分)?
    【解决方案4】:

    Ruby 2.6 adds an exception: argument:

    system('ctat nonexistent.txt', exception: true) # Errno::ENOENT (No such file or directory - ctat)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 2018-12-09
      • 2019-09-16
      • 1970-01-01
      • 2019-09-19
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多