美文网首页
set -e, -u, -o, -x pipefail

set -e, -u, -o, -x pipefail

作者: QXPLUS | 来源:发表于2022-05-11 16:33 被阅读0次

    文章出处:

    The set lines

    • 这些行故意导致您的脚本失败。等等,什么?相信我,这是一件好事。
    • 使用这些设置,某些常见错误将导致脚本立即失败。 否则,您可能会忽略那些隐藏的错误,这些错误只有在生产中才被发现。
    • set -euxo pipefail 是下面4个命令的简称:
    set -e
    set -u
    set -o pipefail
    set -x
    

    set -e

    如果任何命令具有非零的退出状态,该选项指示 bash 立即退出。在所有广泛使用的通用编程语言中,未处理的运行时错误(无论是 Java 中抛出的异常、C 中的分段错误,还是 Python 中的语法错误)都会立即停止程序的执行;不执行后续行。

    • 默认情况下,bash 不这样做。如果您在命令行上使用 bash,则此默认行为正是您想要的
    • 如果脚本中的一行失败,但最后一行成功,则整个脚本都有一个成功的退出代码。这很容易忽略错误。

    set -x

    启用 shell 模式,将所有执行的命令都打印到终端。
    这是 set -x 的典型用例:在执行每个命令时打印它可以帮助您可视化脚本的控制流。

    set -u

    影响变量。
    除了 $*$@,对您之前未定义的任何变量的引用都是一个错误,并导致程序立即退出。
    出于各种充分的理由,Python、C、Java 等语言的行为方式都相同。一个是错别字不会在您没有意识到的情况下创建新变量。

    #!/bin/bash
    firstName="Aaron"
    fullName="$firstname Maxwell"
    echo "$fullName"
    
    • 第三行的右边是“firstname”,全小写,而不是驼峰式的“firstName”。如果没有 -u 选项,这将是一个静默错误。但是使用 -u 选项,脚本在该行以退出代码 1 退出,将消息“firstname: unbound variable”打印到 stderr。
    • 这就是您想要的:让它立即显式失败,而不是创建可能为时已晚发现的细微错误。

    set -o pipefail

    此设置可防止管道中的错误被屏蔽。
    如果管道中的任何命令失败,则该返回码将用作整个管道的返回码。默认情况下,即使成功,管道的返回码也是最后一条命令的返回码。

    $ grep some-string /non/existent/file | sort
    grep: /non/existent/file: No such file or directory
    % echo $?
    0
    
    • 在这里,grep 的退出代码为 2,向 stderr 写入错误消息,向 stdout 写入空字符串。
    • 然后这个空字符串通过 sort,空字符串作为有效输入,并返回状态码 0。
    • 这对命令行很好,但对 shell 脚本不利:您肯定希望脚本立即退出,并使用非零退出代码......像这样:
    $ set -o pipefail
    $ grep some-string /non/existent/file | sort
    grep: /non/existent/file: No such file or directory
    $ echo $?
    2
    

    Setting IFS

    IFS 变量,代表内部字段分隔符

    #!/bin/bash
    IFS=$' '
    items="a b c"
    for x in $items; do
        echo "$x"
    done
    
    IFS=$'\n'
    for y in $items; do
        echo "$y"
    done
    ... will print out this:
    
    a
    b
    c
    a b c
    
    • 对于第一个循环,IFS 是一个空格,这意味着单词由空格字符分隔。
    • 对于第二个循环,“单词”由换行符分隔,这意味着 bash 将“项目”的整个值视为一个单词。如果 IFS 有多个字符,则将对这些字符中的任何一个进行拆分。
    • 为什么我们要将 IFS 设置为由制表符和换行符组成的字符串?因为它在迭代循环时为我们提供了更好的行为。不太可能导致令人惊讶和令人困惑的错误。

    这在使用 bash 数组时很明显:

    #!/bin/bash
    names=(
      "Aaron Maxwell"
      "Wayne Gretzky"
      "David Beckham"
    )
    
    echo "With default IFS value..."
    for name in ${names[@]}; do
      echo "$name"
    done
    
    echo ""
    echo "With strict-mode IFS value..."
    IFS=$'\n\t'
    for name in ${names[@]}; do
      echo "$name"
    done
    
    
    ## 输出结果
    With default IFS value...
    Aaron
    Maxwell
    Wayne
    Gretzky
    David
    Beckham
    
    With strict-mode IFS value...
    Aaron Maxwell
    Wayne Gretzky
    David Beckham
    

    相关文章

      网友评论

          本文标题:set -e, -u, -o, -x pipefail

          本文链接:https://www.haomeiwen.com/subject/pcadurtx.html