Bash: set 命令用法介绍

Bash 在执行脚本的时候,会创建一个新的 shell, 每个 shell 都有自己独立的执行环境,这个环境会有一些默认行为,而这些默认行为可以通过 set 命令来修改。

里介绍几种常用的 set 命令。

注: set 命令在不带参数执行时,会显示当前 shell 的所有环境变量、函数。

set -u 遇到不存在的变量时报错,并停止执行

默认情况下, bash 遇到不存在的变量时会忽略。为了让脚本更加严谨和安全,报错并停止执行是一种更好的选择。

1
2
3
set -u

echo $non_exist_var

Output:

1
bash: line 4: non_exist_var: unbound variable

set -x 运行命令之前,先打印命令本身

1
2
3
4
set -x

unameOutput="$(uname -s)"
echo $unameOutput

Output:

1
2
3
4
++ uname -s
+ unameOutput=Darwin
+ echo Darwin
Darwin

set -e 发生错误时及时终止脚本

默认情况下,脚本执行过程中如果出现运行失败的命令, Bash 会继续执行后面的命令,而这往往是不太安全的行为(因为后面的命令很可能依赖前面命令的成功执行)。

1
2
cd /non/exist/path
echo "do something dangerous like rm files"

Output:

1
2
bash: line 2: cd: /non/exist/path: No such file or directory
do something dangerous like rm files

实践当中,为了避免该问题,我们可以利用逻辑运算符的短路行为来及时终止命令的执行:

1
2
cd /non/exist/path || { echo "/non/exist/path is not found"; exit 1; }
echo "do something dangerous like rm files"

Output:

1
2
bash: line 2: cd: /non/exist/path: No such file or directory
/non/exist/path is not found

这种手工处理的方式比较麻烦,而且容易遗漏。 set -e 命令可以比较好的解决这个问题,该命令设置后,一旦某个命令失败,会立即停止后续命令的执行。

1
2
3
4
set -e

cd /non/exist/path
echo "do something dangerous like rm files"

Output:

1
bash: line 4: cd: /non/exist/path: No such file or directory

set -o pipefail 处理管道错误

set -e 不适用于管道命令,例如:

1
2
3
4
set -e

cat /non/exist/path | echo hello
echo world

Output:

1
2
3
hello
cat: /non/exist/path: No such file or directory
world

set -o pipefail 可以解决该问题:

1
2
3
4
set -eo pipefail

cat /non/exist/path | echo hello
echo world

Output:

1
2
hello
cat: /non/exist/path: No such file or directory

总结

上述四个 set 命令可以按照如下方式一起设置:

1
2
3
4
5
6
# 写法一
set -euxo pipefail

# 写法二
set -eux
set -o pipefail

建议放在所有 Bash 脚本开头。

另外也可以在执行 Bash 脚本时,从命令行传入这些参数:

1
bash -euxo pipefail /path/to/script.sh

参考资料

updatedupdated2023-06-262023-06-26