提交 2fc1edbe authored 作者: 陈泽健's avatar 陈泽健

feat(scripts): 优化数据库备份脚本增加多数据库备份和审计功能

- 实现通用备份函数支持数组形式传入多个数据库
- 增加mysql容器模糊匹配和启动状态检查功能
- 添加磁盘空间检查和同日多次执行防护机制
- 实现分级别日志审计和备份失败汇总报告
- 更新定时任务脚本支持mysql备份参数配置
- 增加定期清理15天前备份数据和日志文件功能
上级 65e7d726
This source diff could not be displayed because it is too large. You can view the blob instead.
# 数据库备份脚本优化
## 代码路径
- 需调用代码路径:[自动化部署脚本/x86架构/新统一平台/定时脚本/UbainsmysqlBakUp.sh]
- 需要同步调整的定时任务脚本:[自动化部署脚本/x86架构/新统一平台/auto_crontab_settings.sh]
## 功能需求
### 功能目标
**目标:** 数据库备份脚本代码逻辑优化,增加数据库:offline、nacos_mysql、devops_voice以及huazhao2的备份操作。
### 需求描述
- 优化现有的代码框架:
- 设置通用备份函数,设置数据库:offline、nacos_mysql、devops_voice以及huazhao2的备份操作,以数组形式传入。
- 增加对mysql容器是否存在的判断,且mysql容器名称需要模糊匹配,例如:umysql、umysql2。以umysql开头的mysql容器,则认为该容器是mysql容器。服务器上mysql容器只会存在一个。如果检查到两个运行的mysql容器那就退出脚本,增加日志说明。
- 添加对mysql容器是否启动的判断,若未启动则退出脚本。
- 若单个数据库备份失败,则跳过该数据库的备份。需要记录失败的数据库名称和原因,且需要一个汇总报告(成功x个,失败x个)
- 备份路径:
- 统一在/data/bakup/mysql下存放,以文件夹形式存放本次备份的数据库文件。文件夹命名为日期格式。
- 通过 docker exec 管道备份到宿主机路径,如:/data/bakup/mysql/`YYYYMMDD`/数据库名称_YYYYMMDD.sql
- 定时清理:
- 默认保留15天的备份数据。超出15天的备份文件夹则删除。清理的位置是/data/bakup/mysql下。通过文件夹名称来判断时间,文件夹名称为日期格式`YYYYMMDD`
- 空间检测判断:
- 检查当前服务器`/data`空间是否小于5G,若小于5G则退出脚本。
- 剩余空间 < 5G(df 命令的 Available)
- 特殊处理:
- 如果在同一天(同一个 YYYYMMDD 文件夹)内多次执行脚本,则退出脚本。
- 日志审计:
- 脚本执行过程中产生的日志,统一存放在/data/bakup/mysql/log下,以日期格式`YYYYMMDD`命名。
- 且日志需记录脚本执行的每一步,要能支撑审计作用。
- 分级别日志,如:INFO、WARN、ERROR。
- 增加时间戳格式,如:2021-01-01 01:01:01。
- 日志文件命名:mysql_$(date +%Y%m%d).log
- 定期清理日志文件,如:mysql_$(date +%Y%m%d).log,默认保留15天的日志文件。
### 数据库连接信息
- 数据库账号:root
- 数据库密码:dNrprU&2S
- 通用命令:docker exec umysql mysqldump -uroot -p"dNrprU&2S" 数据库名 > /data/bakup/mysql/日期/数据库名_日期.sql
### 关联脚本
- 定时任务脚本:[自动化部署脚本/x86架构/新统一平台/auto_crontab_settings.sh]需要增加mysql的参数,可通过接收该参数设置定时任务。
- 数据库定时脚本在服务器上的路径:[/data/services/scripts/UbainsmysqlBakUp.sh]
- 参数名称设置:--enable-mysql-backup 或 --enable-mysql
- 执行周期:每周5晚上0点进行备份。
## 规范文档
- 代码规范: `Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md`
- 问题总结: `Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md`
- 方法总结: `Docs/PRD/01规范文档/_PRD_方法总结_记录文档.md`
- 文档规范: `Docs/PRD/01规范文档/_PRD_规范文档_文档规范.md`
- 测试规范: `Docs/PRD/01规范文档/_PRD_规范文档_测试规范.md`
---
\ No newline at end of file
# 数据库备份脚本优化计划执行文档
> 基于需求文档:`_PRD_数据库备份脚本优化_需求文档.md`
## 1. 代码路径
- **备份脚本路径**`自动化部署脚本/x86架构/新统一平台/定时脚本/UbainsmysqlBakUp.sh`
- **定时任务脚本**`自动化部署脚本/x86架构/新统一平台/auto_crontab_settings.sh`
- **服务器部署路径**`/data/services/scripts/UbainsmysqlBakUp.sh`
---
## 2. 重构目标
### 2.1 核心目标
优化数据库备份脚本,支持多数据库备份,增加容器检查、空间检查、日志审计等功能。
### 2.2 具体要求
- [ ] 通用备份函数,支持数组形式传入多个数据库
- [ ] MySQL 容器模糊匹配(以 umysql 开头)
- [ ] 容器启动状态检查
- [ ] 单库备份失败跳过,记录失败原因
- [ ] 汇总报告(成功x个,失败x个)
- [ ] 空间检查(/data 分区剩余空间 < 5G 则退出)
- [ ] 备份路径:`/data/bakup/mysql/YYYYMMDD/数据库名_YYYYMMDD.sql`
- [ ] 同日多次执行则退出
- [ ] 定时清理:保留 15 天
- [ ] 日志审计:分级别(INFO/WARN/ERROR)、时间戳
---
## 3. 备份数据库列表
| 数据库名称 | 说明 |
|-----------|------|
| offline | 离线数据库 |
| nacos_mysql | Nacos 配置中心数据库 |
| devops_voice | 运维语音数据库 |
| huazhao2 | 华招2号数据库 |
---
## 4. 数据库连接信息
| 项目 | 值 |
|------|-----|
| 用户名 | root |
| 密码 | dNrprU&2S |
| 备份命令 | `docker exec umysql mysqldump -uroot -p"dNrprU&2S" 数据库名 > /data/bakup/mysql/日期/数据库名_日期.sql` |
---
## 5. 定时任务配置
| 项目 | 内容 |
|------|------|
| 任务名称 | mysql_backup |
| Cron 表达式 | `0 0 * * 5`(每周五凌晨 00:00) |
| 脚本路径 | `/data/services/scripts/UbainsmysqlBakUp.sh` |
| 参数名称 | `--enable-mysql-backup``--enable-mysql` |
| 日志输出 | 脚本自身管理,crontab 不重定向 |
---
## 6. 重构设计
### 6.1 脚本结构设计
```
UbainsmysqlBakUp.sh
├── 全局变量定义
│ ├── 数据库列表数组
│ ├── 备份路径配置
│ ├── 数据库连接信息
│ └── 日志配置
├── 日志函数
│ └── log(level, message)
├── 空间检查函数
│ └── check_disk_space()
├── 容器检查函数
│ ├── find_mysql_container()
│ └── check_container_running()
├── 备份函数
│ └── backup_database(db_name, backup_dir)
├── 清理函数
│ ├── cleanup_old_backups()
│ └── cleanup_old_logs()
├── 汇总报告函数
│ └── print_summary()
└── 主函数
└── main()
```
### 6.2 关键函数设计
#### 6.2.1 日志函数
```bash
# 日志配置
LOG_DIR="/data/bakup/mysql/log"
LOG_FILE="${LOG_DIR}/mysql_$(date +%Y%m%d).log"
# 日志函数
function log() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
```
#### 6.2.2 空间检查函数
```bash
function check_disk_space() {
local available_space=$(df /data | awk 'NR==2 {print $4}')
local available_gb=$((available_space / 1024 / 1024))
if [[ $available_gb -lt 5 ]]; then
log "ERROR" "⛔ 磁盘空间不足:当前剩余 ${available_gb}G,要求至少 5G"
return 1
fi
log "INFO" "✅ 磁盘空间检查通过:剩余 ${available_gb}G"
return 0
}
```
#### 6.2.3 容器检查函数
```bash
function find_mysql_container() {
# 查找以 umysql 开头的容器
local containers=$(docker ps --format '{{.Names}}' | grep '^umysql')
# 统计容器数量
local count=$(echo "$containers" | wc -l)
if [[ $count -eq 0 ]]; then
log "ERROR" "⛔ 未找到 MySQL 容器(以 umysql 开头)"
return 1
fi
if [[ $count -gt 1 ]]; then
log "ERROR" "⛔ 检测到多个 MySQL 容器:"
echo "$containers" | while read -r container; do
log "ERROR" " - $container"
done
return 1
fi
MYSQL_CONTAINER=$(echo "$containers" | head -n 1)
log "INFO" "✅ 找到 MySQL 容器: $MYSQL_CONTAINER"
return 0
}
```
#### 6.2.4 备份函数
```bash
function backup_database() {
local db_name="$1"
local backup_dir="$2"
local date_str=$(date +%Y%m%d)
local backup_file="${backup_dir}/${db_name}_${date_str}.sql"
log "INFO" "🔧 开始备份数据库: $db_name"
# 执行备份
if docker exec "$MYSQL_CONTAINER" mysqldump -uroot -p"dNrprU&2S" "$db_name" > "$backup_file" 2>/dev/null; then
log "INFO" "✅ 数据库备份成功: $db_name"
((SUCCESS_COUNT++))
return 0
else
log "ERROR" "⛔ 数据库备份失败: $db_name"
((FAILED_COUNT++))
FAILED_DBS+=("$db_name")
return 1
fi
}
```
#### 6.2.5 清理函数
```bash
function cleanup_old_backups() {
local backup_base="/data/bakup/mysql"
log "INFO" "🧹 开始清理旧备份文件..."
# 查找并删除 15 天前的备份文件夹
find "$backup_base" -maxdepth 1 -type d -name "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" -mtime +15 -exec rm -rf {} \; 2>/dev/null
log "INFO" "✅ 旧备份文件清理完成"
}
function cleanup_old_logs() {
local log_dir="/data/bakup/mysql/log"
log "INFO" "🧹 开始清理旧日志文件..."
# 删除 15 天前的日志文件
find "$log_dir" -name "mysql_*.log" -mtime +15 -delete 2>/dev/null
log "INFO" "✅ 旧日志文件清理完成"
}
```
#### 6.2.6 汇总报告函数
```bash
function print_summary() {
local total=$((SUCCESS_COUNT + FAILED_COUNT))
log "INFO" "=========================================="
log "INFO" "📊 备份汇总报告"
log "INFO" "=========================================="
log "INFO" "总计数据库:$total 个"
log "INFO" "成功备份:$SUCCESS_COUNT 个"
log "INFO" "失败备份:$FAILED_COUNT 个"
if [[ ${#FAILED_DBS[@]} -gt 0 ]]; then
log "INFO" "失败列表:"
for db in "${FAILED_DBS[@]}"; do
log "INFO" " - $db"
done
fi
log "INFO" "=========================================="
}
```
### 6.3 主函数流程
```bash
function main() {
# 初始化统计变量
SUCCESS_COUNT=0
FAILED_COUNT=0
FAILED_DBS=()
# 数据库列表
DATABASES=("offline" "nacos_mysql" "devops_voice" "huazhao2")
# 获取当前日期
local today=$(date +%Y%m%d)
local backup_dir="/data/bakup/mysql/$today"
# 创建日志目录
mkdir -p "$LOG_DIR"
log "INFO" "=========================================="
log "INFO" "🚀 开始数据库备份"
log "INFO" "=========================================="
# 1. 空间检查
if ! check_disk_space; then
exit 1
fi
# 2. 容器检查
if ! find_mysql_container; then
exit 1
fi
# 3. 检查容器是否启动
if ! check_container_running; then
exit 1
fi
# 4. 检查今日是否已备份
if [[ -d "$backup_dir" ]]; then
log "ERROR" "⛔ 今日备份文件夹已存在:$backup_dir"
log "ERROR" "⛔ 为避免覆盖,脚本退出"
exit 1
fi
# 5. 创建备份目录
mkdir -p "$backup_dir"
log "INFO" "📁 创建备份目录: $backup_dir"
# 6. 执行备份
for db_name in "${DATABASES[@]}"; do
backup_database "$db_name" "$backup_dir"
done
# 7. 清理旧文件
cleanup_old_backups
cleanup_old_logs
# 8. 打印汇总报告
print_summary
log "INFO" "✅ 数据库备份完成"
}
```
---
## 7. 定时任务脚本更新
### 7.1 需要添加的任务定义
`auto_crontab_settings.sh` 中添加:
```bash
# mysql_backup 任务定义
TASK_CRON[mysql_backup]="0 0 * * 5"
TASK_SCRIPT[mysql_backup]="/data/services/scripts/UbainsmysqlBakUp.sh"
TASK_LOG[mysql_backup]=""
TASK_STATUS[mysql_backup]=true # 默认启用
```
### 7.2 需要添加的参数处理
```bash
--enable-mysql-backup)
TASK_STATUS[mysql_backup]=true
;;
--disable-mysql-backup)
TASK_STATUS[mysql_backup]=false
;;
--enable-mysql)
TASK_STATUS[mysql_backup]=true
;;
--disable-mysql)
TASK_STATUS[mysql_backup]=false
;;
```
---
## 8. 实现步骤
### 8.1 阶段一:备份脚本实现
- [ ] 步骤 1:创建日志函数和全局变量
- [ ] 步骤 2:实现空间检查函数
- [ ] 步骤 3:实现容器检查函数
- [ ] 步骤 4:实现备份函数
- [ ] 步骤 5:实现清理函数
- [ ] 步骤 6:实现汇总报告函数
- [ ] 步骤 7:实现主函数流程
### 8.2 阶段二:定时任务脚本更新
- [ ] 步骤 8:在 `auto_crontab_settings.sh` 中添加 mysql_backup 任务定义
- [ ] 步骤 9:添加参数处理逻辑
- [ ] 步骤 10:更新帮助信息
### 8.3 阶段三:测试验证
- [ ] 步骤 11:功能测试
- 空间检查测试
- 容器检查测试
- 单库备份测试
- 多库备份测试
- 失败处理测试
- 清理功能测试
- [ ] 步骤 12:定时任务测试
- 参数测试
- crontab 配置测试
---
## 9. 测试用例
| 用例编号 | 测试场景 | 预期结果 |
|----------|----------|----------|
| TC-MYSQL-01 | 空间充足时备份 | 备份成功,所有数据库备份完成 |
| TC-MYSQL-02 | 空间不足时备份 | 记录错误日志,退出脚本 |
| TC-MYSQL-03 | 容器不存在时备份 | 记录错误日志,退出脚本 |
| TC-MYSQL-04 | 多个容器时备份 | 记录错误日志,列出容器名,退出脚本 |
| TC-MYSQL-05 | 容器未启动时备份 | 记录错误日志,退出脚本 |
| TC-MYSQL-06 | 单库备份失败 | 跳过该数据库,继续备份其他数据库 |
| TC-MYSQL-07 | 同日多次执行 | 记录错误日志,退出脚本 |
| TC-MYSQL-08 | 清理功能测试 | 删除 15 天前的备份和日志 |
| TC-MYSQL-09 | 汇总报告测试 | 正确显示成功/失败数量和列表 |
| TC-MYSQL-10 | 日志审计测试 | 每步操作都有日志记录,包含时间戳和级别 |
---
## 10. 规范文档
- 代码规范: `Docs/PRD/01规范文档/_PRD_规范文档_代码规范.md`
- 问题总结: `Docs/PRD/01规范文档/_PRD_问题总结_记录文档.md`
- 方法总结: `Docs/PRD/01规范文档/_PRD_方法总结_记录文档.md`
- 文档规范: `Docs/PRD/01规范文档/_PRD_规范文档_文档规范.md`
- 测试规范: `Docs/PRD/01规范文档/_PRD_规范文档_测试规范.md`
---
## 11. 优化功能回填
> 本章节用于记录开发过程中发现的优化点,开发完成后回填到需求文档。
| 序号 | 优化内容 | 状态 | 说明 |
|------|----------|------|------|
| 1 | 备份文件空值检查 | ✅ 已实现 | 备份完成后检查文件是否为空,避免空备份文件占用空间 |
| 2 | 清理操作日志增强 | ✅ 已实现 | 清理操作记录删除的文件数量,便于审计 |
| 3 | 退出码优化 | ✅ 已实现 | 根据备份结果设置退出码,部分失败时返回非零退出码 |
| 4 | 日志双重输出 | ✅ 已实现 | 日志同时输出到控制台和文件,便于实时监控和后续审计 |
---
**文档版本:** v1.1
**创建日期:** 2026-04-10
**最后更新:** 2026-04-10
**更新内容:** 完成代码实现,新增优化功能回填记录
#!/bin/bash
#####################################
#用于数据库备份 23-01-13
#####################################
#预定数据库备份
function ubainsbak()
{
echo -e "\033[33m 检查mysql...... \033[0m"
sudo docker images |grep mysql
sudo docker ps |grep umysql
if [ $? -eq 0 ]; then
sudo docker exec -i umysql bash <<'EOF'
find /home/mysql/ubains/* -mtime +30 -exec rm -rf {} \;
mkdir -p /home/mysql/ubains/$(date +%Y%m%d)
# 备份指定数据库
mysqldump -uroot -p"dNrprU&2S" ubains > /home/mysql/ubains/$(date +%Y%m%d)/ubains_$(date +%Y%m%d_%H%M%S).sql
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
rm /home/mysql/ubains/$log3* -rf
exit
EOF
sudo mkdir -p /data/bakup/mysql/ubains/$(date +%Y%m%d)
sudo docker cp umysql:/home/mysql/ubains/$(date +%Y%m%d) /data/bakup/mysql/ubains
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
sudo rm /data/bakup/mysql/ubains/$log3* -rf
else
echo -e "\033[33m 请正确安装数据库...... \033[0m"
fi
}
#运维数据库备份
function devopsbak()
{
echo -e "\033[33m 检查mysql...... \033[0m"
sudo docker images |grep mysql
sudo docker ps |grep umysql
if [ $? -eq 0 ]; then
sudo docker exec -i umysql bash <<'EOF'
find /home/mysql/devops/* -mtime +30 -exec rm -rf {} \;
mkdir -p /home/mysql/devops/$(date +%Y%m%d)
# 备份指定数据库
mysqldump -uroot -p"dNrprU&2S" devops > /home/mysql/devops/$(date +%Y%m%d)/devops_$(date +%Y%m%d_%H%M%S).sql
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
rm /home/mysql/devops/$log3* -rf
exit
EOF
sudo mkdir -p /data/bakup/mysql/devops/$(date +%Y%m%d)
sudo docker cp umysql:/home/mysql/devops/$(date +%Y%m%d) /data/bakup/mysql/devops
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
sudo rm /data/bakup/mysql/devops/$log3* -rf
else
echo -e "\033[33m 请正确安装数据库...... \033[0m"
fi
}
#############################################################脚本配置项##################################################################################################
#################预定系统 数据库本地备份###############################
ubainsbak
#################运维系统 数据库本地备份###############################
devopsbak
......@@ -26,6 +26,12 @@ TASK_SCRIPT[check_health]="/data/services/scripts/check_server_health.sh"
TASK_LOG[check_health]=""
TASK_STATUS[check_health]=true # 默认启用
# mysql_backup 任务定义
TASK_CRON[mysql_backup]="0 0 * * 5"
TASK_SCRIPT[mysql_backup]="/data/services/scripts/UbainsmysqlBakUp.sh"
TASK_LOG[mysql_backup]=""
TASK_STATUS[mysql_backup]=true # 默认启用
# 初始化 sudo 相关变量
if [[ $(id -u) -ne 0 ]]; then
SUDO="sudo"
......@@ -59,6 +65,10 @@ function show_help() {
--disable-ujava2 禁用 ujava2-startup 定时任务
--enable-check-health 启用 check_server_health 定时任务
--disable-check-health 禁用 check_server_health 定时任务
--enable-mysql-backup 启用 mysql_backup 定时任务
--disable-mysql-backup 禁用 mysql_backup 定时任务
--enable-mysql 启用 mysql_backup 定时任务(别名)
--disable-mysql 禁用 mysql_backup 定时任务(别名)
-h, --help 显示此帮助信息
默认行为:
......@@ -66,8 +76,9 @@ function show_help() {
示例:
$0 # 默认启用所有任务
$0 --disable-ujava2 # 只启用 check_server_health
$0 --enable-ujava2 --enable-check-health # 显式启用指定任务
$0 --disable-ujava2 # 禁用 ujava2-startup
$0 --enable-mysql-backup # 启用数据库备份
$0 --enable-ujava2 --enable-check-health --enable-mysql-backup # 显式启用所有任务
EOF
}
......@@ -101,6 +112,17 @@ function parse_arguments() {
TASK_STATUS[check_health]=false
fi
;;
--enable-mysql-backup|--enable-mysql)
TASK_STATUS[mysql_backup]=true
;;
--disable-mysql-backup|--disable-mysql)
if [[ "${TASK_STATUS[mysql_backup]}" == "false" ]]; then
log "WARN" "⚠️ 参数冲突:mysql_backup 同时被启用和禁用,跳过该任务"
TASK_STATUS[mysql_backup]=conflict
else
TASK_STATUS[mysql_backup]=false
fi
;;
-h|--help)
show_help
exit 0
......
#!/bin/bash
# ========================================
# 数据库备份脚本
# 功能:多数据库备份、容器检查、空间检查、日志审计
# ========================================
# ========================================
# 全局变量定义
# ========================================
# 数据库列表(数组形式)
DATABASES=("offline" "nacos_mysql" "devops_voice" "huazhao2")
# 备份路径配置
BACKUP_BASE="/data/bakup/mysql"
LOG_DIR="${BACKUP_BASE}/log"
# 数据库连接信息
DB_USER="root"
DB_PASSWORD="dNrprU&2S"
# MySQL 容器名称(动态获取)
MYSQL_CONTAINER=""
# 统计变量
SUCCESS_COUNT=0
FAILED_COUNT=0
FAILED_DBS=()
# 日志文件
LOG_FILE="${LOG_DIR}/mysql_$(date +%Y%m%d).log"
# 初始化 sudo 相关变量
if [[ $(id -u) -ne 0 ]]; then
SUDO="sudo"
else
SUDO=""
fi
# ========================================
# 日志函数
# ========================================
function log() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 输出到控制台
echo "[$timestamp] [$level] $message"
# 追加到日志文件
if [[ -n "$LOG_FILE" ]]; then
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
fi
}
# ========================================
# ✅ 函数:检查磁盘空间
# ========================================
function check_disk_space() {
log "INFO" "🔍 检查磁盘空间..."
local available_space=$(df /data | awk 'NR==2 {print $4}')
local available_gb=$((available_space / 1024 / 1024))
if [[ $available_gb -lt 5 ]]; then
log "ERROR" "⛔ 磁盘空间不足:当前剩余 ${available_gb}G,要求至少 5G"
return 1
fi
log "INFO" "✅ 磁盘空间检查通过:剩余 ${available_gb}G"
return 0
}
# ========================================
# ✅ 函数:查找 MySQL 容器
# ========================================
function find_mysql_container() {
log "INFO" "🔍 查找 MySQL 容器..."
# 查找以 umysql 开头且正在运行的容器
local containers=$(docker ps --format '{{.Names}}' | grep '^umysql')
# 统计容器数量
local count=$(echo "$containers" | grep -c '^umysql' 2>/dev/null || echo 0)
if [[ $count -eq 0 ]]; then
log "ERROR" "⛔ 未找到 MySQL 容器(以 umysql 开头且正在运行)"
return 1
fi
if [[ $count -gt 1 ]]; then
log "ERROR" "⛔ 检测到多个 MySQL 容器:"
echo "$containers" | while read -r container; do
log "ERROR" " - $container"
done
log "ERROR" "⛔ 为避免误操作,脚本退出"
return 1
fi
MYSQL_CONTAINER=$(echo "$containers" | head -n 1)
log "INFO" "✅ 找到 MySQL 容器: $MYSQL_CONTAINER"
return 0
}
# ========================================
# ✅ 函数:检查容器是否启动
# ========================================
function check_container_running() {
log "INFO" "🔍 检查容器运行状态..."
if ! docker ps --format '{{.Names}}' | grep -q "^${MYSQL_CONTAINER}$"; then
log "ERROR" "⛔ MySQL 容器未启动: $MYSQL_CONTAINER"
return 1
fi
log "INFO" "✅ MySQL 容器运行正常"
return 0
}
# ========================================
# ✅ 函数:备份数据库
# ========================================
function backup_database() {
local db_name="$1"
local backup_dir="$2"
local date_str=$(date +%Y%m%d)
local backup_file="${backup_dir}/${db_name}_${date_str}.sql"
log "INFO" "🔧 开始备份数据库: $db_name"
# 执行备份
if docker exec "$MYSQL_CONTAINER" mysqldump -u"${DB_USER}" -p"${DB_PASSWORD}" "$db_name" > "$backup_file" 2>/dev/null; then
# 检查备份文件是否为空
if [[ -s "$backup_file" ]]; then
log "INFO" "✅ 数据库备份成功: $db_name"
((SUCCESS_COUNT++))
return 0
else
log "ERROR" "⛔ 数据库备份失败: $db_name (备份文件为空)"
((FAILED_COUNT++))
FAILED_DBS+=("$db_name")
rm -f "$backup_file"
return 1
fi
else
log "ERROR" "⛔ 数据库备份失败: $db_name (mysqldump 执行失败)"
((FAILED_COUNT++))
FAILED_DBS+=("$db_name")
return 1
fi
}
# ========================================
# ✅ 函数:清理旧备份文件
# ========================================
function cleanup_old_backups() {
log "INFO" "🧹 开始清理旧备份文件..."
# 删除 15 天前的备份文件夹
local deleted_count=$(find "$BACKUP_BASE" -maxdepth 1 -type d -name "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" -mtime +15 -print -exec rm -rf {} \; 2>/dev/null | wc -l)
if [[ $deleted_count -gt 0 ]]; then
log "INFO" "✅ 已删除 ${deleted_count} 个旧备份文件夹"
else
log "INFO" "✅ 无需清理的旧备份文件夹"
fi
}
# ========================================
# ✅ 函数:清理旧日志文件
# ========================================
function cleanup_old_logs() {
log "INFO" "🧹 开始清理旧日志文件..."
# 删除 15 天前的日志文件
local deleted_count=$(find "$LOG_DIR" -name "mysql_*.log" -mtime +15 -print -delete 2>/dev/null | wc -l)
if [[ $deleted_count -gt 0 ]]; then
log "INFO" "✅ 已删除 ${deleted_count} 个旧日志文件"
else
log "INFO" "✅ 无需清理的旧日志文件"
fi
}
# ========================================
# ✅ 函数:打印汇总报告
# ========================================
function print_summary() {
local total=$((SUCCESS_COUNT + FAILED_COUNT))
log "INFO" "=========================================="
log "INFO" "📊 备份汇总报告"
log "INFO" "=========================================="
log "INFO" "总计数据库:$total 个"
log "INFO" "成功备份:$SUCCESS_COUNT 个"
log "INFO" "失败备份:$FAILED_COUNT 个"
if [[ ${#FAILED_DBS[@]} -gt 0 ]]; then
log "INFO" "失败列表:"
for db in "${FAILED_DBS[@]}"; do
log "INFO" " - $db"
done
fi
log "INFO" "=========================================="
# 根据备份结果决定退出码
if [[ $FAILED_COUNT -gt 0 ]]; then
return 1
else
return 0
fi
}
# ========================================
# ✅ 函数:主函数
# ========================================
function main() {
# 获取当前日期
local today=$(date +%Y%m%d)
local backup_dir="${BACKUP_BASE}/${today}"
# 创建日志目录
$SUDO mkdir -p "$LOG_DIR"
log "INFO" "=========================================="
log "INFO" "🚀 开始数据库备份"
log "INFO" "=========================================="
log "INFO" "备份日期: $today"
log "INFO" "备份数据库数量: ${#DATABASES[@]}"
# 1. 空间检查
if ! check_disk_space; then
log "INFO" "=========================================="
log "ERROR" "⛔ 备份失败:磁盘空间不足"
log "INFO" "=========================================="
exit 1
fi
# 2. 容器检查
if ! find_mysql_container; then
log "INFO" "=========================================="
log "ERROR" "⛔ 备份失败:MySQL 容器检查失败"
log "INFO" "=========================================="
exit 1
fi
# 3. 检查容器是否启动
if ! check_container_running; then
log "INFO" "=========================================="
log "ERROR" "⛔ 备份失败:MySQL 容器未启动"
log "INFO" "=========================================="
exit 1
fi
# 4. 检查今日是否已备份
if [[ -d "$backup_dir" ]]; then
log "ERROR" "⛔ 今日备份文件夹已存在:$backup_dir"
log "ERROR" "⛔ 为避免覆盖,脚本退出"
log "INFO" "=========================================="
log "ERROR" "⛔ 备份失败:今日已备份"
log "INFO" "=========================================="
exit 1
fi
# 5. 创建备份目录
$SUDO mkdir -p "$backup_dir"
log "INFO" "📁 创建备份目录: $backup_dir"
# 6. 执行备份
for db_name in "${DATABASES[@]}"; do
backup_database "$db_name" "$backup_dir"
done
# 7. 清理旧文件
cleanup_old_backups
cleanup_old_logs
# 8. 打印汇总报告
print_summary
local exit_code=$?
if [[ $exit_code -eq 0 ]]; then
log "INFO" "✅ 数据库备份完成"
else
log "ERROR" "⛔ 数据库备份完成,但部分数据库备份失败"
fi
exit $exit_code
}
# ========================================
# 主函数入口
# ========================================
main
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论