Bash 'set -euxo pipefail'讲解

本文详细介绍如何通过在Bash脚本中使用'set-euxopipefail'增强脚本安全性,包括错误处理、未定义变量检测、命令执行前打印、信号捕捉及管道失败策略,确保脚本稳定可靠。

bash脚本被当作高级语言应用默认的不会开启安全认证(类似其他语言,变量不存在会报错,bash默认不会)。

为了让我们的脚本更安全通常我们会使用‘set -euxo pipefail'。

‘set -euxo pipefail’的功能为:

  • ’-e‘: 当一个命令失败时,立即退出。如果你不想立即退出则可用‘|| true’
    $ cat try_bash.sh 
    #!/bin/sh
    set -e
    test_sete(){
      # invalid command
      ddd
    }
    
    test_sete || true
    echo "---> continuly"
    $ ./try_bash.sh 
    ./try_bash.sh: line 5: ddd: command not found
    ---> continuly
    $ vi try_bash.sh 
    $ sed -i 's/|| true//' try_bash.sh 
    $ cat try_bash.sh 
    #!/bin/sh
    set -e
    test_sete(){
      # invalid command
      ddd
    }
    
    test_sete 
    echo "---> continuly"
    $ ./try_bash.sh 
    ./try_bash.sh: line 5: ddd: command not found
    

     

  • ‘-u’: 遇到未定义的变量,报错并立即退出。
    $ cat try_bash_u.sh 
    #!/bin/sh
    set -u
    test_setu(){
      # invalid command
      echo ${1}
    }
    test_setu ${1}
    echo "---> continuly"
    $ ./try_bash_u.sh testing
    testing
    ---> continuly
    $ ./try_bash_u.sh 
    ./try_bash_u.sh: line 7: 1: unbound variable
    

     

  • ’-x‘: 在执行每一个command之前打印出来。这个对于debug脚本非常有用,可具体看到在执行那一步遇到的问题。但是所有的参数也都会相应的在执行脚本以明文形式输出。
    $ ./try_bash_x.sh testing
    + test_setu testing
    + echo testing
    testing
    + echo '---> continuly'
    ---> continuly
    

     

  • ‘-E’: 'trap'用来在一个脚本中捕捉某些信号。除了一些常见的信号,'trap'可以用来捕捉一些特定信号,像EXIT,DEBUG, RETURN,ERR等。没有’-E‘, trap会不总是能捕捉信号。如果出现'trap'不道的情况,可以使用该参数。如果捕捉信号正常,则可以忽略该参数。
    $ cat try_bash_E.sh 
    #!/bin/bash
    set -E
    
    trap "echo ERR trap fired!" ERR
    
    myfunc()
    {
      # 'foo' is a non-existing command
      foo
    }
    
    myfunc
    echo "bar"
    $ ./try_bash_E.sh 
    ./try_bash_E.sh: line 9: foo: command not found
    ERR trap fired!
    ERR trap fired!
    bar
    $ sed -i "s/set -E//" try_bash_E.sh 
    $ ./try_bash_E.sh 
    ./try_bash_E.sh: line 9: foo: command not found
    ERR trap fired!
    bar
    

     

  • '-o pipefail': 在运行脚本时,通常我们只看最后一个命令的退出码。例如'invalid_command || echo "invalid command"',我们获得退出码为0,因为我们获得整个管道的最后一个命令。加上’-o pipefail‘,则会根据整个管道链的退出码来判断,只有所有退出码为0,退出码才会为0。
    $ cat try_bash_o.sh 
    #!/bin/bash
    set -e -o pipefail
    # 'foo' is a non-existing command
    foo | echo "a"
    echo "bar"
    
    $ ./try_bash_o.sh 
    a
    ./try_bash_o.sh: line 5: foo: command not found
    $ echo $?
    127
    $ sed -i 's/-o pipefail//' try_bash_o.sh 
    $ ./try_bash_o.sh 
    a
    ./try_bash_o.sh: line 5: foo: command not found
    bar
    $ echo $?
    0
    
    [Click and drag to move]
    ​

     

<think>好的,我现在需要解释用户提到的“set -euo pipefail”这个命令的含义。首先,我得分解每个选项的作用。-e选项是让脚本在任何命令失败时立即退出,这样可以避免后续命令继续执行导致问题。接下来是-u选项,它会让脚本在引用未定义的变量时报错,这样可以防止拼写错误或者未初始化的变量带来的问题。然后是-o pipefail,这个选项的作用是当管道中的任何一个命令失败时,整个管道返回失败状态,这样能更准确地捕获错误。 接下来,我需要考虑用户的使用场景。用户可能在编写bash脚本,希望增强脚本的健壮性,确保错误能被正确处理。可能他们遇到了脚本中某些命令失败但未被检测到的问题,导致后续步骤出错,所以想通过这个命令来改进。 用户可能没有说出来的需求是希望他们的脚本能更可靠地处理错误,避免静默失败的情况。他们可能希望了解每个选项的具体作用,以及如何组合使用这些选项来提高脚本的稳定性。 我需要确保解释每个选项时准确无误,可能还要给出例子说明这些选项如何影响脚本的行为。例如,当使用-e时,如果某个命令返回非零状态,脚本会立即退出,而不是继续执行。使用-u可以防止变量未定义的问题,比如当变量名拼写错误时,脚本会报错而不是继续执行。 另外,关于pipefail选项,需要解释管道命令中各个命令的状态如何影响整体结果。通常情况下,管道的返回状态是最后一个命令的状态,但启用pipefail后,如果有任何一个命令失败,整个管道就会返回失败状态,这样更方便错误检测。 最后,我应该提醒用户这些选项的常见用法和注意事项,比如某些情况下可能需要临时禁用-e选项,或者如何处理特殊情况。这样用户能更全面地理解如何应用这些设置。</think>`set -euo pipefail` 是 Bash 脚本中常用的组合命令,用于增强脚本的健壮性。其含义如下: 1. **`-e`**:遇到任何命令返回非 0 状态(即失败)时立即退出脚本。 2. **`-u`**:尝试使用未定义的变量时抛出错误(避免变量名拼写错误导致意外行为)。 3. **`-o pipefail`**:管道命令中若任意一个子命令失败,整个管道返回失败状态(默认仅返回最后一个命令的状态)。 例如: ```bash set -euo pipefail # 若 grep 失败,整个管道返回错误,脚本退出 cat data.txt | grep "error" | wc -l ``` ### 注意事项 - 某些场景需临时禁用 `-e`(如允许特定命令失败):`command || true` - 未定义变量引用会被捕获:`echo $UNDEFINED_VAR` 会触发错误。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值