error-handling - 保持 set -e 设置在里面 ||或者 &&

标签 error-handling sh posix

我有一个简单的脚本,它有一个简单的函数,可能会导致错误。让我们定义这个函数,并将其破坏:

brokenFunction () {
    ls "non-existing-folder"
}

如果我们在一个 block 中执行这个函数来检测它是否被破坏,它会很好地工作:
brokenFunction || printf "It is broken\n"

打印“它坏了”

现在,让我们通过在末尾添加一个正确的命令来使函数更复杂一点:
#!/bin/sh

brokenFunction () {
    ls "non-existing-folder"
    printf "End of function\n"
}

brokenFunction || printf "It is broken\n"

此脚本打印:
$ ./script.sh 
ls: cannot access 'non-existing-folder': No such file or directory
End of function

虽然我希望函数在 printf 语句之前停止,并且下一个 block 显示“它已损坏”。

事实上,如果我检查 brokenFunction 的退出状态代码, 为 0。

我尝试添加 set -e到脚本的顶部。行为仍然相同,但退出代码为 brokenFunction如果在没有 || 的情况下调用现在变成 2 .如果用它调用,状态码仍然是0 .

有什么办法可以保留set -e在使用 || 调用的函数内设置?

编辑:我刚刚意识到示例中的函数没用。我在一个简单的 block 和一个条件下遇到了同样的问题。
#!/bin/sh
set -e
{
    ls "non-existing-dir"
    printf "End of block\n"
} || {
    printf "It is broken\n"
} 

打印
$ ./script.sh 
ls: cannot access 'non-existing-dir': No such file or directory
End of block

最佳答案

man bash 中所写, set -e在某些情况下被忽略。 || 之前的命令或 &&就是这样一个语境。
trap在这里看起来像是一个可能的解决方案。使用 trap 的最后一个脚本的可行替代方案看起来像这样:

#!/bin/sh
abort () {
    printf "It is broken\n"
}
trap 'abort' ERR
(
    set -e
    false
    printf "End of block\n"
)
trap - ERR

这里有几点需要注意:
  • trap 'abort' ERR绑定(bind)abort对任何引发的错误起作用;
  • 损坏的 block 在子外壳中执行有两个原因。首先是将 set -e 设置保留在 block 内并限制边框效果。其次是在出错时退出这个子shell(set -e 效果),而不是整个脚本;
  • trap - ERR最后重置trap绑定(bind),意味着脚本的以下部分像以前一样执行。

  • 为了测试边框效果,我们可以添加之前不工作的部分:
    #!/bin/sh
    abort () {
        printf "It is broken\n"
    }
    
    trap 'abort' ERR
    (
        set -e
        false
        printf "End of block\n"
    )
    trap - ERR
    
    {   
        false
        printf "End of second block\n"
    } || {
        printf "It is broken too\n"
    }
    

    打印:
    It is broken
    End of second block
    

    关于error-handling - 保持 set -e 设置在里面 ||或者 &&,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46180753/

    相关文章:

    linux - 尝试从文本文件中获取实例 ID

    php - 在终端中运行 php 脚本时得到空输出

    创建使用 getaddrinfo 的静态链接二进制文件?

    python - numpy std计算: TypeError: cannot perform reduce with flexible type

    swift - “ fatal error :在展开可选值时意外发现nil”是什么意思?

    javascript - 动态加载音频的src并在src不存在后停止

    正则表达式在 C 中不起作用

    java - SimpleDateFormat 解析时间异常

    c# - 如何使用 nohup 在 Mono 中执行进程?

    c++ - 如何通过虚拟寻址区中的指针获取物理寻址区中的地址?