Bash 'set -euxo pipefail'讲解

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]
    ​

     

你可能感兴趣的:(linux,usages)