一、介绍

通常情况下,对于经常使用高级语言编写程序的小伙伴来说,比如我们在程序中使用了一个未定义的变量,程序就会抛出一个错误。但是对于bash来说,它不会有任何报错信息,并且继续往下执行。

为了改变默认的shell行为,bash为我们提供了set命令帮助我们来编写更安全的shell脚本。我们来看一些详细的使用案例。

二、 set -e:

当命令执行失败时(命令退出状态码 不等于 0 ),-e选项会使bash立即退出。

未使用 :

#!/bin/bash

# 'foo'执行一个不存在的命令
foo
echo "bar"

# 输出:
# ------
# line 4: foo: command not found
# bar

使用后:

#!/bin/bash
set -e

# 'foo' 执行一个不存在的命令
foo
echo "bar"

# output
# ------
# line 5: foo: command not found
#不在往下执行。

执行foo发现不存在,shell会立即停止执行。

如果我们希望,执行到错误命令时继续往下执行,我们可以在命令后 添加 || true,我们看示例:

#!/bin/bash
set -e

foo || true
$(ls foobar) || true
echo "bar"

# output
# ------
# line 4: foo: command not found
# ls: foobar: No such file or directory
# bar  执行到这了。

三、set -o pipefail:

如果我们的命令有管道符操作,命令退出后的状态码是由最后一层管道符决定的。-e它只能对管道最后一个命令的退出状态码执行操作。而-o选项将管道的退出代码设置为管道的所有命令都成功退出,则设置为零。

未使用:

#!/bin/bash
set -e

# 'foo'不存在的命令
foo | echo "a"  
echo "bar"

# output
# ------
# a
# line 5: foo: command not found
# bar

上述代码成功输出bar,管道符操作命令最终退出状态码为 0

使用后:

#!/bin/bash
set -eo pipefail

# 'foo'不存在的命令
foo | echo "a"
echo "bar"

# output
# ------
# a
# line 5: foo: command not found

我们使用了-o pipefail参数,由于使用了不存在命令 foo,退出状态码不为0,所以将停止执行。

四、set -u:

-u参数用来检测不存在的变量,默认情况下在shell中使用不存在的变量,不会做任何错误输出。设置-u参数后,shell将未设置的变量视为错误并立即退出。这也是我们最安全的shell编写方式。

未使用:

#!/bin/bash
set -eo pipefail

echo $a
echo "bar"

# output
# ------
#
# bar 正常输出
#

我们看到,代码中我们使用了未定义变量$a,程序没有抛出错误,并且继续执行。

使用后:

#!/bin/bash
set -euo pipefail

echo "$a"
echo "bar"

# output
# ------
# line 5: a: unbound variable

我们看到程序抛出了错误,并停止后续执行。

五、set -x:

默认情况下,执行bash脚本后,只显示输出结果,我们不知道输出的结果是哪一行执行的,-x帮助我们显示执行的代码行。

#!/bin/bash
set -euxo pipefail

a=5
echo $a
echo "bar"

# output
# ------
# + a=5
# + echo 5
# 5
# + echo bar
# bar

六、总结:

通常我们使用set -euxo pipefail 组合来使得我们的bash更加健壮。这也是我们所希望的,在编写每一个bash时在头部加上这些参数。

七、参考:

Safer bash scripts,by vaneyckt


Leave Your Comment

电子邮件地址不会被公开。 必填项已用*标注