Ubuntu 脚本优化与备份恢复逻辑修正

学习笔记作者:admin日期:2025-07-26点击:17

摘要:本文总结了对一个用于监控 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
最新备份查找 按时间排序更好

上一篇      下一篇