set -e 是 Shell 脚本中让脚本在任意命令返回非零状态码时立即终止的内置选项,可避免错误被掩盖、防止连锁故障,但条件语句、管道、子 shell 及显式忽略错误(如 || true)等场景不触发终止。

写 Shell 脚本时,加一句 set -e 是最简单、最有效的防错手段之一。它不是锦上添花的调试技巧,而是让脚本“不带病运行”的底线保障。
让错误不被掩盖
默认情况下,Shell 脚本会一路执行到底,哪怕中间某条命令失败(比如 cp 找不到源文件、curl 下载超时、grep 没匹配到内容),后续命令仍照常运行。结果可能是:日志里写了一堆“成功”,实际却漏处理了关键步骤。
set -e 改变这一点——只要任意一条命令返回非零状态码(即失败),脚本立刻终止,不再往下走。
- 避免“雪球效应”:一个失败的
mkdir导致后续所有touch都写进错误路径 - 防止误删或误覆盖:
rm -rf $DEST失败后,cp -r $SRC $DEST不会盲目执行 - 部署脚本更可信:git pull 失败就停,不会继续 build 和 deploy 错误代码
哪些地方不会触发终止?要心里有数
set -e 并非机械式拦截每处失败,它尊重 Shell 的逻辑上下文。以下情况即使命令失败,脚本也继续执行:
- 出现在
if、while、until条件判断中的命令(例如if ! command; then ... fi) - 用
&&或||连接的命令链中,失败是流程设计的一部分(如command || echo "忽略此错误") - 在子 shell 中执行:
( command_that_fails )不影响父脚本 - 显式用
|| true或|| :吞掉退出码
这种“智能豁免”其实是优点——它让你能自然地写容错逻辑,而不是处处加 if 判断。
配合其他选项效果更好
set -e 常和另外两个选项一起用,构成基础健壮性组合:
-
set -u:引用未定义变量时报错退出,避免
$USER_NAME拼成$USERNMAE还静默运行 - set -x:打印每条展开后的命令,方便定位到底是哪一步出问题(调试时开,上线前关)
常见开头写法:
#!/bin/bashset -euo pipefail
其中 pipefail 让管道中任一环节失败都算整体失败(默认只看最后一个命令)。
临时关闭 set -e 的正确方式
真遇到必须容忍失败的场景(比如检查某个文件是否存在),别硬写 command || true,更清晰的做法是:
- 用
set +e临时关闭,执行完再set -e恢复 - 或直接用
if包裹:if ! command; then echo "可接受失败"; fi
注意:不要在函数内部随意 set -e 又不恢复,容易影响调用方行为。

















