Ubuntu 脚本优化与备份恢复逻辑修正
摘要:本文总结了对一个用于监控 PostgreSQL 数据目录大小变化并执行备份恢复的 Bash 脚本进行的检查和优化。重点修正了查找最大备份文件的逻辑,并增强了脚本的健壮性和安全性。
一、脚本功能概述
该脚本的主要功能是:监控 /root/dockerdata/postgres/ 目录的大小变化,如果增长过慢或减少超过 10MB,则停止 Docker 容器,从最新备份中恢复数据,并重新启动服务。
二、问题分析与改进点
1. 权限问题
使用了 chmod -R 777
,这会带来安全隐患。建议改为更合理的权限设置,例如使用 chown -R 999:999
设置正确的用户和组。
2. 变量未加引号
在 shell 脚本中,路径或文件名包含空格时会导致错误。建议为所有变量加上双引号,例如:du -sm "/root/dockerdata/postgres/"
。
3. find 命令可能返回空值
find
命令如果没有找到备份文件,maxfile
将为空,后续解压会失败。建议添加判断,如:if [ -z "$maxfile" ] || [ ! -f "$maxfile" ]; then ... fi
。
4. 逻辑判断中的负数处理不严谨
if [ $diff -gt -10 ]; then
这个条件允许 -9 ~ +∞
的范围,但语义上更清晰的是 if [ $diff -ge -10 ]; then
。
5. 缺少错误处理机制
很多命令如 rm
, tar
, docker stop/start
等都可能失败,但脚本并没有做任何错误检测。建议添加 set -e
来中断脚本遇到错误。
6. 缺少日志输出
脚本没有输出任何信息,不利于调试和运维。建议添加一些日志打印,方便排查问题。
7. sleep 时间太长
两次 sleep 20
可能没有必要,PostgreSQL 容器启动一般不会这么久。可以缩短等待时间,或者使用健康检查替代固定等待。
8. 备份文件格式假设单一
假设备份是 .tar.gz
格式,且文件名排序即时间顺序。这种做法不够可靠。建议按修改时间排序,确保获取最新的备份文件。
三、改进后的脚本版本
#!/bin/bash
set -e # 遇到错误立即退出
SCRIPT_DIR=$(dirname "$0")
LASTSIZE_FILE="$SCRIPT_DIR/lastsize.txt"
# 获取 lastsize,若不存在则初始化为 0
if [ -f "$LASTSIZE_FILE" ]; then
lastsize=$(cat "$LASTSIZE_FILE")
else
lastsize=0
echo "$lastsize" > "$LASTSIZE_FILE"
fi
# 获取当前目录大小(MB)
justsize=$(du -sm "/root/dockerdata/postgres/" | awk '{print $1}')
# 计算差值
diff=$((justsize - lastsize))
# 输出日志
echo "$(date '+%Y-%m-%d %H:%M:%S') - Current size: ${justsize}MB, Last size: ${lastsize}MB, Diff: ${diff}MB"
# 判断是否正常增长或轻微减小
if [ $diff -ge -10 ]; then
echo "Size change is within acceptable range."
echo "$justsize" > "$LASTSIZE_FILE"
exit 0
else
echo "Detected abnormal size drop. Restoring from backup..."
# 停止容器
docker stop bitmagnet || true
sleep 5
docker stop bitmagnet-postgres || true
sleep 5
# 查找最大备份文件
maxfile=$(find /www/backup/path/postgres -type f -name "*.tar.gz" -printf '%s %p\n' | sort -nr | head -1 | cut -d' ' -f2-)
if [ -z "$maxfile" ] || [ ! -f "$maxfile" ]; then
echo "Error: No valid backup file found!" >&2
exit 1
fi
echo "Restoring from backup file: $maxfile"
# 删除旧数据
rm -rf "/root/dockerdata/postgres/"
# 解压新数据
mkdir -p "/root/dockerdata/"
tar -xzf "$maxfile" -C "/root/dockerdata/"
# 设置权限(建议用 chown 替代 chmod 777)
chown -R 999:999 "/root/dockerdata/postgres/"
# 启动容器
docker start bitmagnet-postgres
sleep 10
docker start bitmagnet
# 重置 lastsize
echo "0" > "$LASTSIZE_FILE"
echo "Restore completed successfully."
fi
四、其他建议
- 将该脚本加入 crontab 定期运行,比如每天一次。
- 使用 systemd timer 或 supervisor 管理脚本运行周期。
- 添加邮件或通知接口,在发生恢复操作时发送警报。
五、总结
项目 | 状态 | 建议 |
---|---|---|
功能实现 | ✅ | 正常 |
变量引用安全 | ❗ | 加双引号 |
文件路径处理 | ❗ | 检查是否存在 |
错误处理 | ❌ | 增加 set -e 或手动判断 |
日志输出 | ❌ | 增加日志便于排错 |
权限设置 | ❌ | 改为合理 chown |
最新备份查找 | ❗ | 按时间排序更好 |