写出更健壮的 Bash 脚本:set -euo pipefail 与几个好习惯

举报
yd_256733395 发表于 2026/11/03 14:56:56 2026/11/03
【摘要】 很多运维小脚本一开始只有几行,能跑就行。可一旦放进定时任务或部署流程,问题就来了:中间某条命令失败了,脚本却继续往下执行,最后把错误的结果当成成功;变量拼错了名字,rm 命令删掉了意料之外的目录。其实 Bash 本身提供了几个开关和写法,能让脚本在出错时及时停下来。本文整理几条最实用的习惯。一、开头加上 set -euo pipefail在脚本第二行写上 set -euo pipefail,...

很多运维小脚本一开始只有几行,能跑就行。可一旦放进定时任务或部署流程,问题就来了:中间某条命令失败了,脚本却继续往下执行,最后把错误的结果当成成功;变量拼错了名字,rm 命令删掉了意料之外的目录。其实 Bash 本身提供了几个开关和写法,能让脚本在出错时及时停下来。本文整理几条最实用的习惯。

一、开头加上 set -euo pipefail

在脚本第二行写上 set -euo pipefail,可以一次打开三个保护:

  • -e:任何命令返回非零就立即退出,不再继续执行后面的步骤。
  • -u:引用未定义的变量时直接报错,避免因为拼写错误得到空字符串。
  • -o pipefail:管道中任意一段失败,整个管道就算失败。默认情况下只看最后一段,像 curl ... | grep ok 这样的写法,curl 失败了也可能被忽略。

需要允许某条命令失败时,可以显式写成 command || true,让意图一目了然。

二、变量一律加双引号

写 rm -rf $DIR/tmp 时,如果 DIR 为空,实际执行的就是 rm -rf /tmp;如果路径里有空格,又会被拆成多个参数。养成写 "$DIR" 的习惯,再配合 -u,或者用 ${DIR:?DIR 未设置} 在变量为空时直接报错退出,能挡住很多事故。

三、用 trap 做清理

脚本经常会创建临时文件。如果中途出错退出,这些文件就留在磁盘上。可以这样写:

tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT

无论脚本是正常结束还是因为错误退出,EXIT 陷阱都会执行,临时文件总能被清理掉。同样的方法也可以用来释放锁文件。

四、输出带时间的日志

定时任务出问题时,最缺的就是日志。写一个简单的函数:

log() { echo "[$(date '+%F %T')] $*" >&2; }

关键步骤前后调用一次,并把输出重定向到日志文件,事后排查就能看出卡在了哪一步、用了多久。把日志写到标准错误,也不会污染需要被其他程序读取的标准输出。

五、交给 ShellCheck 把关

ShellCheck 是一个静态检查工具,能发现未加引号的变量、错误的条件判断、不可移植的语法等问题。大部分发行版可以直接用包管理器安装,执行 shellcheck deploy.sh 就能看到逐行提示。把它加进代码提交前的检查,团队里的脚本质量会明显提高。

小结

Bash 脚本写起来快,但默认行为相当“宽容”,很多错误会被悄悄吞掉。开头的 set -euo pipefail、变量加引号、trap 清理、带时间戳的日志,再加上 ShellCheck 检查,这几步花不了几分钟,却能让脚本在云服务器上长期稳定地运行。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。