Shell 脚本防坑指南:set -euo pipefail 与常见死法实录
写 Shell 脚本十年,见过太多「在我机器上明明能跑」的灵异现场。九成问题出在脚本没有防御性设置。本文把最关键的几条保命符一次讲透。
一、三件套:set -euo pipefail
#!/bin/bash
set -euo pipefail
- -e:任何命令失败立刻退出,不让错误滚雪球
- -u:引用未定义变量直接报错,抓住拼写错误
- -o pipefail:管道中任何一环失败都算整体失败。没有它,cmd1 | cmd2 里 cmd1 崩了,退出码会被 cmd2 的成功覆盖
二、常见死法实录
死法1:变量没加引号。rm -rf $DIR 在 DIR 为空时等于 rm -rf,直接清空当前目录。正确写法 rm -rf "$DIR"。
死法2:cd 失败继续跑。cd /data && rm -rf tmp 看着安全,但若上一行 cd 失败且没 set -e,后面的相对路径操作全跑在错误目录。cd ... || exit 1 双保险。
死法3:管道退出码被吞。gzip -t backup.gz | grep -q error 返回 0 就以为备份健康——gzip 崩了退出码也被 grep 的成功覆盖。pipefail 专治这个。
死法4:$? 用晚了。中间插了一行 echo,if [ $? -eq 0 ] 检查的就是 echo 的退出码。
三、调试三板斧
- bash -n script.sh:只做语法检查不执行
- bash -x script.sh:打印每条命令再执行
- set -x / set +x:脚本内局部开启关闭,缩小排查范围
四、进阶习惯
- 用 mktemp -d 建临时目录并 trap 'rm -rf "$TMPDIR"' EXIT 兜底清理
- 本地变量一律 local(函数内)
- shellcheck 静态扫描接入 CI,一劳永逸
防御性脚本写法的本质:让失败尽早、尽响亮地暴露。出错不可怕,静默出错才致命。
- 点赞
- 收藏
- 关注作者
评论(0)