智享教程网
白蓝主题五 · 清爽阅读
首页  > 日常经验

Bash脚本错误处理的实用技巧分享

Bash脚本时,很多人只关注功能能不能跑通,却忽略了出错时该怎么办。等到脚本在服务器上半夜自动运行,一个命令失败导致后续全乱套,第二天才发现备份没成功、日志被覆盖,那就晚了。

让脚本在出错时立即停下

默认情况下,Bash脚本会一条条执行命令,哪怕中间某一步失败了也继续往下走。这很危险。比如下面这个例子:

cp important.conf /backup/
mkdir /data/logs
rm -rf /old/temp/*

如果磁盘满了,cp失败了,但脚本还是继续删临时文件——这不是我们想要的。加一行就能解决:

set -e

加上这句后,只要任意命令返回非零状态,脚本立刻退出。简单粗暴,但很有效。

别让未定义变量毁掉你的命令

有时候变量拼错了,或者环境没加载好,变量是空的。比如:

rm -rf /home/$USERDATA/

如果USERDATA没定义,那这条命令就变成了rm -rf /home//,等于清空整个目录。加上这句可以提前发现问题:

set -u

这样,引用未定义变量时脚本会直接报错退出。

追踪到底哪一行出了问题

光知道出错了还不够,得知道在哪出的错。配合set -e,再加上:

set -x

可以让脚本运行时打印每一条实际执行的命令,方便定位问题。不过输出会变多,适合调试阶段开启。

用 trap 捕获异常,做清理工作

有些任务需要善后。比如脚本创建了临时文件,中途出错也要删掉。可以用trap

TEMP_DIR=/tmp/myapp.$$
mkdir $TEMP_DIR

cleanup() {
rm -rf $TEMP_DIR
echo "临时文件已清理"
}

trap cleanup EXIT

无论脚本正常结束还是中途退出,trap都会触发cleanup函数。这对保持系统整洁很重要。

检查关键命令的结果

有些错误你得自己判断。比如下载文件,失败了要重试:

if ! wget http://example.com/data.zip; then
echo "下载失败,尝试重试..."
sleep 2
wget http://example.com/data.zip || {
echo "重试也失败了"; exit 1
}
fi

if !判断命令失败,再决定怎么处理,比盲目往下走强得多。

组合使用更安全

实际写脚本时,通常一开头就写:

#!/bin/bash
set -eu

-e遇到错误退出,-u遇到未定义变量报错,两条一起用,能挡住大多数低级失误。

写自动化脚本不是写玩具,谁都会犯错,关键是让错误早点暴露,别偷偷积累到最后爆炸。加几行防护代码,省下半夜爬起来救火的时间,不香吗?