Compare commits

..

3 Commits

Author SHA1 Message Date
a00314964d feat(backup): 添加单文件备份功能
- 添加 files 配置节,支持备份多个单独文件
- 实现 backup_files() 函数,处理单文件备份逻辑
- 更新 merge_backups() 函数,支持合并 files 备份
- 更新配置文件示例,添加 files 配置说明
- 更新 README 文档:
  - 添加单文件备份功能说明
  - 添加 files 配置示例
  - 添加单文件恢复详细步骤
  - 更新备份文件结构说明
  - 添加单文件完整性验证方法
  - 添加 v1.3.0 更新日志

使用场景:
- 备份配置文件(如 /etc/nginx/nginx.conf)
- 备份环境变量文件(如 /opt/app/.env)
- 备份其他重要的单个文件

备份结构:
backup.tar.gz
├── folders/folders.tar.gz  # 文件夹备份
├── files/files.tar.gz      # 单文件备份
└── mysql/mysql.sql.gz      # 数据库备份
2025-12-26 13:06:33 +08:00
Wang Defa
8d1ad4a642 docs: 完善 README 文档
- 添加 docker-backup update 自动更新命令说明
- 添加详细的备份恢复指南,包含 SQL.gz 多种恢复方法
- 添加 keep_count 和 keep_days 清理策略详细说明
- 添加备份验证完整性方法
- 添加完整恢复到新服务器的示例
- 添加恢复注意事项和最佳实践
- 添加 3-2-1 备份策略说明
- 添加异地备份示例(rsync、rclone)
- 添加更新日志 v1.2.0
- 添加贡献指南和相关链接
2025-12-25 17:26:16 +08:00
Wang Defa
0459136442 feat(backup): 实现 keep_count 清理策略和自动更新功能
- 添加 keep_count 配置读取,支持按数量保留备份
- 实现基于文件数量的清理逻辑,保留最新的 N 个备份文件
- 添加 docker-backup update 自动更新命令,从远程仓库拉取最新版本
- 添加 docker-backup help 帮助信息,显示完整使用说明
- 优化清理策略:优先使用 keep_days,其次使用 keep_count
- 添加版本备份和错误恢复机制,确保更新安全
2025-12-25 17:23:43 +08:00
3 changed files with 636 additions and 15 deletions

372
README.md
View File

@@ -5,6 +5,7 @@
## 功能特性 ## 功能特性
-**文件夹备份**: 打包指定文件夹为 tar.gz 压缩文件 -**文件夹备份**: 打包指定文件夹为 tar.gz 压缩文件
-**单文件备份**: 支持备份多个单独的配置文件(如 .env、config.yml 等)
-**排除目录**: 支持配置需要排除的文件夹和文件模式 -**排除目录**: 支持配置需要排除的文件夹和文件模式
-**MySQL 备份**: 备份 MySQL 容器数据库为 sql.gz 压缩文件 -**MySQL 备份**: 备份 MySQL 容器数据库为 sql.gz 压缩文件
-**合并打包**: 将文件夹和数据库备份合并为单个压缩文件 -**合并打包**: 将文件夹和数据库备份合并为单个压缩文件
@@ -76,6 +77,7 @@ backup:
retention: retention:
enabled: true # 是否启用自动清理 enabled: true # 是否启用自动清理
keep_days: 7 # 保留最近 N 天的备份 keep_days: 7 # 保留最近 N 天的备份
# keep_count: 10 # 或保留最近 N 个备份(与 keep_days 二选一)
# 文件夹备份配置 # 文件夹备份配置
folders: folders:
@@ -88,6 +90,14 @@ folders:
- "*/temp" - "*/temp"
- "*/cache" - "*/cache"
# 单文件备份配置
files:
enabled: true # 是否启用单文件备份
sources: # 需要备份的文件列表
- "/etc/docker-backup/config.yml"
- "/etc/nginx/nginx.conf"
- "/opt/app/.env"
# MySQL 数据库备份配置 # MySQL 数据库备份配置
mysql: mysql:
enabled: true # 是否启用 MySQL 备份 enabled: true # 是否启用 MySQL 备份
@@ -108,6 +118,22 @@ logging:
## 使用指南 ## 使用指南
### 更新工具
```bash
# 更新到最新版本
sudo docker-backup update
# 显示帮助信息
docker-backup help
```
更新功能会:
- 自动从远程仓库下载最新版本
- 备份当前版本(以防更新失败)
- 同时更新 backup.sh 和 cleanup.sh
- 更新失败时自动回滚
### 定时任务管理 ### 定时任务管理
```bash ```bash
@@ -140,6 +166,35 @@ docker-backup
sudo journalctl -u docker-backup.service -f sudo journalctl -u docker-backup.service -f
``` ```
### 备份清理策略
工具支持两种清理策略:
#### 策略一按天数清理keep_days
保留最近 N 天的备份,删除更早的备份。
```yaml
backup:
retention:
enabled: true
keep_days: 7 # 保留最近 7 天的备份
```
#### 策略二按数量清理keep_count
保留最近 N 个备份文件,删除多余的旧备份。
```yaml
backup:
retention:
enabled: true
# keep_days: 7 # 注释掉 keep_days
keep_count: 10 # 只保留最近 10 个备份
```
**优先级**:如果同时配置了 `keep_days``keep_count`,将优先使用 `keep_days` 策略。
### 备份文件管理 ### 备份文件管理
```bash ```bash
@@ -204,8 +259,205 @@ backup-20250125-143022.tar.gz
``` ```
backup-20250125-143022.tar.gz backup-20250125-143022.tar.gz
├── folders.tar.gz # 文件夹备份 ├── folders/
└── mysql.sql.gz # MySQL 数据库备份 │ └── folders.tar.gz # 文件夹备份
├── files/
│ └── files.tar.gz # 单文件备份
└── mysql/
└── mysql.sql.gz # MySQL 数据库备份
```
## 备份恢复
### 1. 解压备份文件
```bash
# 进入备份目录
cd /var/backups/docker-backup
# 解压主备份文件
tar -xzf backup-20250125-143022.tar.gz
# 查看解压内容
ls -lh
# folders/ mysql/
```
### 2. 恢复文件夹
```bash
# 解压文件夹备份
cd folders
tar -xzf folders.tar.gz
# 查看解压的文件
ls -lh
# 将显示备份时的完整路径opt/gitea/
# 方法一:直接恢复到原位置(会覆盖现有文件)
sudo cp -r opt/gitea/* /opt/gitea/
# 方法二:恢复到临时目录检查
mkdir -p /tmp/restore
cp -r opt/gitea /tmp/restore/
# 检查无误后再复制到目标位置
```
### 3. 恢复单个文件
```bash
# 解压单文件备份
cd ../files
tar -xzf files.tar.gz
# 查看解压的文件
ls -lh
# 将显示备份时的完整路径etc/docker-backup/config.yml
# 方法一:直接恢复到原位置(会覆盖现有文件)
sudo cp etc/docker-backup/config.yml /etc/docker-backup/
sudo cp etc/nginx/nginx.conf /etc/nginx/
sudo cp opt/app/.env /opt/app/
# 方法二:选择性恢复
# 只恢复需要的文件
sudo cp etc/nginx/nginx.conf /etc/nginx/
# 方法三:恢复到临时目录检查
mkdir -p /tmp/restore-files
cp -r etc /tmp/restore-files/
# 检查无误后再复制到目标位置
```
### 4. 恢复 MySQL 数据库
#### 方法一:恢复到 Docker 容器
```bash
# 解压 SQL 文件
cd ../mysql
gunzip -c mysql.sql.gz > mysql.sql
# 恢复到 MySQL 容器
docker exec -i mysql mysql -uroot -p'your_password' < mysql.sql
# 或者恢复单个数据库
docker exec -i mysql mysql -uroot -p'your_password' database_name < mysql.sql
# 清理临时文件
rm mysql.sql
```
#### 方法二:恢复指定数据库
```bash
# 先解压查看备份内容
gunzip -c mysql.sql.gz | less
# 恢复特定数据库
gunzip -c mysql.sql.gz | docker exec -i mysql mysql -uroot -p'your_password' database_name
```
#### 方法三:分步恢复(推荐用于生产环境)
```bash
# 1. 先测试 SQL 文件是否完整
gunzip -t mysql.sql.gz
echo "测试通过: SQL 文件完整"
# 2. 解压到临时位置
gunzip -c mysql.sql.gz > /tmp/restore_mysql.sql
# 3. 检查 SQL 文件内容
head -n 50 /tmp/restore_mysql.sql
tail -n 50 /tmp/restore_mysql.sql
# 4. 停止应用(避免数据写入)
# docker-compose down # 根据实际情况
# 5. 备份当前数据库(以防恢复失败)
docker exec mysql mysqldump -uroot -p'your_password' --all-databases | gzip > /tmp/current_backup.sql.gz
# 6. 执行恢复
docker exec -i mysql mysql -uroot -p'your_password' < /tmp/restore_mysql.sql
# 7. 验证恢复结果
docker exec mysql mysql -uroot -p'your_password' -e "SHOW DATABASES;"
# 8. 重启应用
# docker-compose up -d # 根据实际情况
# 9. 清理临时文件
rm /tmp/restore_mysql.sql
```
### 5. 完整恢复示例
假设需要完整恢复到新服务器:
```bash
# 1. 复制备份文件到新服务器
scp backup-20250125-143022.tar.gz root@new-server:/tmp/
# 2. 在新服务器上解压
cd /tmp
tar -xzf backup-20250125-143022.tar.gz
# 3. 恢复文件夹
cd folders
tar -xzf folders.tar.gz
sudo cp -r opt/gitea /opt/
# 4. 启动 MySQL 容器(如果还没启动)
docker-compose up -d mysql
# 5. 等待 MySQL 启动完成
sleep 10
# 6. 恢复数据库
cd ../mysql
gunzip -c mysql.sql.gz | docker exec -i mysql mysql -uroot -p'your_password'
# 7. 验证恢复
docker exec mysql mysql -uroot -p'your_password' -e "SHOW DATABASES;"
ls -lh /opt/gitea/
# 8. 启动所有服务
docker-compose up -d
```
### 6. 恢复注意事项
⚠️ **重要提示**
1. **备份当前数据**:恢复前务必备份当前数据
2. **停止应用**:恢复数据库时建议停止应用,避免数据冲突
3. **测试恢复**:在生产环境恢复前,建议先在测试环境验证
4. **权限问题**:恢复文件后检查文件所有者和权限
5. **版本兼容**:确保 MySQL 版本兼容(备份和恢复的版本)
6. **磁盘空间**:确保有足够的磁盘空间进行解压和恢复
### 7. 验证备份完整性
```bash
# 测试 tar.gz 文件完整性
tar -tzf backup-20250125-143022.tar.gz > /dev/null
echo "主备份文件完整"
# 测试 SQL 压缩文件完整性
cd mysql
gunzip -t mysql.sql.gz
echo "SQL 备份文件完整"
# 测试文件夹备份完整性
cd ../folders
tar -tzf folders.tar.gz > /dev/null
echo "文件夹备份完整"
# 测试单文件备份完整性
cd ../files
tar -tzf files.tar.gz > /dev/null
echo "单文件备份完整"
``` ```
## 故障排查 ## 故障排查
@@ -306,25 +558,123 @@ docker-backup/
4. **异地备份**: 建议将备份文件同步到远程服务器或云存储。 4. **异地备份**: 建议将备份文件同步到远程服务器或云存储。
5. **监控备份**: 配置通知功能,及时了解备份状态。
## 最佳实践
### 1. 3-2-1 备份策略
推荐采用 3-2-1 备份策略:
- **3** 份数据副本1 份原始数据 + 2 份备份)
- **2** 种不同的存储介质(如本地硬盘 + 云存储)
- **1** 份异地备份
### 2. 定期验证备份
建议每月进行一次完整的恢复测试:
```bash
# 1. 创建测试环境
mkdir -p /tmp/backup-test
# 2. 解压最新备份
cd /tmp/backup-test
tar -xzf /var/backups/docker-backup/backup-latest.tar.gz
# 3. 验证文件完整性
cd folders && tar -tzf folders.tar.gz
cd ../mysql && gunzip -t mysql.sql.gz
# 4. 测试数据库恢复(可选)
# 在测试容器中恢复并验证
```
### 3. 备份前的准备
- 确保有足够的磁盘空间(至少是数据大小的 2 倍)
- 在数据库负载较低时执行备份
- 记录备份配置变更历史
### 4. 异地备份示例
使用 rsync 同步到远程服务器:
```bash
# 添加到定时任务或备份后钩子
rsync -avz --delete \
/var/backups/docker-backup/ \
user@remote-server:/backups/
```
使用 rclone 同步到云存储:
```bash
# 安装 rclone
# 配置云存储(如 S3、Google Drive 等)
rclone config
# 同步备份到云存储
rclone sync /var/backups/docker-backup/ remote:backup/
```
## 更新日志
### v1.3.0 (2025-12-26)
- ✨ 新增支持单个文件备份功能files 配置)
- 📝 文档:添加单文件备份和恢复的详细说明
- 🔧 优化:备份文件结构更清晰,支持文件夹、单文件、数据库分类备份
### v1.2.0 (2025-12-25)
- ✨ 新增:支持 `keep_count` 按数量保留备份策略
- ✨ 新增:`docker-backup update` 自动更新功能
- ✨ 新增:`docker-backup help` 帮助命令
- 🐛 修复:清理策略未正确执行的问题
- 📝 文档:添加详细的备份恢复指南
### v1.1.0 (2025-01-25)
- 📝 文档:完善使用说明和故障排查
- 🔧 优化:改进日志输出格式
### v1.0.0 (2025-01-25)
- 🎉 初始版本发布
- ✅ 支持文件夹备份
- ✅ 支持 MySQL 容器备份
- ✅ 支持定时任务
- ✅ 支持自动清理旧备份
- ✅ 提供一键安装脚本
## 贡献 ## 贡献
欢迎提交 Issue 和 Pull Request 欢迎提交 Issue 和 Pull Request
### 贡献指南
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'feat: 添加某个功能'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 提交 Pull Request
请遵循项目的代码规范和提交信息格式(参考 Conventional Commits
## 许可证 ## 许可证
MIT License MIT License
## 作者 ## 作者
Your Name wangdefa
## 更新日志 ## 相关链接
### v1.0.0 (2025-01-25) - **项目主页**: https://gitea.bcde.io/wangdefa/docker-backup
- **问题反馈**: https://gitea.bcde.io/wangdefa/docker-backup/issues
- **文档**: https://gitea.bcde.io/wangdefa/docker-backup/wiki
- 初始版本发布 ## 致谢
- 支持文件夹备份
- 支持 MySQL 容器备份 感谢所有贡献者的支持和反馈!
- 支持定时任务
- 支持自动清理旧备份
- 提供一键安装脚本

View File

@@ -146,10 +146,14 @@ load_config() {
# 读取清理策略 # 读取清理策略
RETENTION_ENABLED=$(yq eval '.backup.retention.enabled' "${CONFIG_FILE}") RETENTION_ENABLED=$(yq eval '.backup.retention.enabled' "${CONFIG_FILE}")
KEEP_DAYS=$(yq eval '.backup.retention.keep_days' "${CONFIG_FILE}") KEEP_DAYS=$(yq eval '.backup.retention.keep_days' "${CONFIG_FILE}")
KEEP_COUNT=$(yq eval '.backup.retention.keep_count' "${CONFIG_FILE}")
# 读取文件夹备份配置 # 读取文件夹备份配置
FOLDERS_ENABLED=$(yq eval '.folders.enabled' "${CONFIG_FILE}") FOLDERS_ENABLED=$(yq eval '.folders.enabled' "${CONFIG_FILE}")
# 读取单文件备份配置
FILES_ENABLED=$(yq eval '.files.enabled' "${CONFIG_FILE}")
# 读取 MySQL 配置 # 读取 MySQL 配置
MYSQL_ENABLED=$(yq eval '.mysql.enabled' "${CONFIG_FILE}") MYSQL_ENABLED=$(yq eval '.mysql.enabled' "${CONFIG_FILE}")
MYSQL_CONTAINER=$(yq eval '.mysql.container_name' "${CONFIG_FILE}") MYSQL_CONTAINER=$(yq eval '.mysql.container_name' "${CONFIG_FILE}")
@@ -255,6 +259,68 @@ backup_folders() {
fi fi
} }
###############################################################################
# 备份单个文件
###############################################################################
backup_files() {
if [[ "${FILES_ENABLED}" != "true" ]]; then
log_info "单文件备份未启用,跳过"
return 0
fi
log_info "开始备份单个文件..."
# 创建临时目录
local temp_backup_dir="${TEMP_DIR}/files"
mkdir -p "${temp_backup_dir}"
# 获取要备份的文件数量
local source_count=$(yq eval '.files.sources | length' "${CONFIG_FILE}")
if [[ "${source_count}" == "0" ]] || [[ "${source_count}" == "null" ]]; then
log_warn "未配置要备份的文件"
return 0
fi
# 收集要备份的文件
local files_tar="${temp_backup_dir}/files.tar.gz"
local tar_sources=""
local valid_files=0
for i in $(seq 0 $((source_count - 1))); do
local source_file=$(yq eval ".files.sources[$i]" "${CONFIG_FILE}")
if [[ ! -f "${source_file}" ]]; then
log_warn "源文件不存在,跳过: ${source_file}"
continue
fi
tar_sources+=" ${source_file}"
valid_files=$((valid_files + 1))
log_info "添加备份文件: ${source_file}"
done
if [[ ${valid_files} -eq 0 ]]; then
log_warn "没有有效的备份文件"
return 0
fi
# 执行打包
log_info "开始打包文件..."
# 将 tar 的 stdout 和 stderr 都重定向到 stderr避免干扰函数返回值
eval "tar -czf '${files_tar}' ${tar_sources}" >&2 2>&1
if [[ -f "${files_tar}" ]]; then
local tar_size=$(du -h "${files_tar}" | cut -f1)
log_info "文件备份完成: ${files_tar} (大小: ${tar_size})"
echo "${files_tar}"
else
log_error "文件备份失败"
return 1
fi
}
############################################################################### ###############################################################################
# 备份 MySQL 数据库 # 备份 MySQL 数据库
############################################################################### ###############################################################################
@@ -330,7 +396,8 @@ backup_mysql() {
merge_backups() { merge_backups() {
local folders_tar=$1 local folders_tar=$1
local mysql_dump=$2 local files_tar=$2
local mysql_dump=$3
log_info "开始合并备份文件..." log_info "开始合并备份文件..."
@@ -345,6 +412,10 @@ merge_backups() {
files_to_pack+=" ${folders_tar}" files_to_pack+=" ${folders_tar}"
fi fi
if [[ -n "${files_tar}" ]] && [[ -f "${files_tar}" ]]; then
files_to_pack+=" ${files_tar}"
fi
if [[ -n "${mysql_dump}" ]] && [[ -f "${mysql_dump}" ]]; then if [[ -n "${mysql_dump}" ]] && [[ -f "${mysql_dump}" ]]; then
files_to_pack+=" ${mysql_dump}" files_to_pack+=" ${mysql_dump}"
fi fi
@@ -361,6 +432,10 @@ merge_backups() {
files_list+=" ${folders_tar#${TEMP_DIR}/}" files_list+=" ${folders_tar#${TEMP_DIR}/}"
log_info "添加到合并: ${folders_tar#${TEMP_DIR}/} ($(du -h "${folders_tar}" | cut -f1))" log_info "添加到合并: ${folders_tar#${TEMP_DIR}/} ($(du -h "${folders_tar}" | cut -f1))"
fi fi
if [[ -n "${files_tar}" ]] && [[ -f "${files_tar}" ]]; then
files_list+=" ${files_tar#${TEMP_DIR}/}"
log_info "添加到合并: ${files_tar#${TEMP_DIR}/} ($(du -h "${files_tar}" | cut -f1))"
fi
if [[ -n "${mysql_dump}" ]] && [[ -f "${mysql_dump}" ]]; then if [[ -n "${mysql_dump}" ]] && [[ -f "${mysql_dump}" ]]; then
files_list+=" ${mysql_dump#${TEMP_DIR}/}" files_list+=" ${mysql_dump#${TEMP_DIR}/}"
log_info "添加到合并: ${mysql_dump#${TEMP_DIR}/} ($(du -h "${mysql_dump}" | cut -f1))" log_info "添加到合并: ${mysql_dump#${TEMP_DIR}/} ($(du -h "${mysql_dump}" | cut -f1))"
@@ -394,24 +469,180 @@ cleanup_old_backups() {
log_info "开始清理旧备份..." log_info "开始清理旧备份..."
# 优先使用 keep_days 策略
if [[ "${KEEP_DAYS}" != "null" ]] && [[ "${KEEP_DAYS}" =~ ^[0-9]+$ ]]; then if [[ "${KEEP_DAYS}" != "null" ]] && [[ "${KEEP_DAYS}" =~ ^[0-9]+$ ]]; then
log_info "删除 ${KEEP_DAYS} 天前的备份文件..." log_info "使用保留天数策略: 删除 ${KEEP_DAYS} 天前的备份文件..."
# 查找并删除旧文件 # 查找并删除旧文件
find "${OUTPUT_DIR}" -name "${BACKUP_PREFIX}-*.tar.gz" -type f -mtime +${KEEP_DAYS} -print | while read old_file; do find "${OUTPUT_DIR}" -name "${BACKUP_PREFIX}-*.tar.gz" -type f -mtime +${KEEP_DAYS} -print | while read old_file; do
log_info "删除旧备份: ${old_file}" log_info "删除旧备份: ${old_file}"
rm -f "${old_file}" rm -f "${old_file}"
done done
# 如果没有设置 keep_days使用 keep_count 策略
elif [[ "${KEEP_COUNT}" != "null" ]] && [[ "${KEEP_COUNT}" =~ ^[0-9]+$ ]]; then
log_info "使用保留数量策略: 保留最近 ${KEEP_COUNT} 个备份文件..."
# 获取所有备份文件,按修改时间倒序排列(最新的在前)
local backup_files=($(find "${OUTPUT_DIR}" -name "${BACKUP_PREFIX}-*.tar.gz" -type f -printf '%T@ %p\n' | sort -rn | awk '{print $2}'))
local total_files=${#backup_files[@]}
log_info "当前备份文件总数: ${total_files}"
# 如果文件数量超过保留数量,删除多余的
if [[ ${total_files} -gt ${KEEP_COUNT} ]]; then
local files_to_delete=$((total_files - KEEP_COUNT))
log_info "需要删除 ${files_to_delete} 个旧备份文件"
# 删除超出保留数量的文件(从数组末尾开始,即最旧的文件)
for ((i=${KEEP_COUNT}; i<${total_files}; i++)); do
local old_file="${backup_files[$i]}"
log_info "删除旧备份: ${old_file}"
rm -f "${old_file}"
done
else
log_info "备份文件数量未超过保留限制,无需清理"
fi
else
log_info "未配置有效的清理策略,跳过清理"
fi fi
log_info "清理完成" log_info "清理完成"
} }
###############################################################################
# 更新脚本
###############################################################################
update_script() {
log_info "=========================================="
log_info "Docker Backup 自动更新"
log_info "=========================================="
# 检查 root 权限
if [[ $EUID -ne 0 ]]; then
log_error "更新功能需要 root 权限"
log_info "请使用: sudo docker-backup update"
exit 1
fi
# 远程仓库地址
local repo_url="https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main"
# 安装路径
local bin_dir="/usr/local/bin"
local backup_script="${bin_dir}/docker-backup"
local cleanup_script="${bin_dir}/docker-backup-cleanup"
log_info "从远程仓库更新脚本..."
log_info "仓库地址: ${repo_url}"
# 备份当前版本
if [[ -f "${backup_script}" ]]; then
local backup_backup="${backup_script}.backup"
log_info "备份当前 backup.sh 到: ${backup_backup}"
cp "${backup_script}" "${backup_backup}"
fi
if [[ -f "${cleanup_script}" ]]; then
local cleanup_backup="${cleanup_script}.backup"
log_info "备份当前 cleanup.sh 到: ${cleanup_backup}"
cp "${cleanup_script}" "${cleanup_backup}"
fi
# 下载新版本 backup.sh
log_info "下载最新 backup.sh..."
if command -v wget &> /dev/null; then
if ! wget -q "${repo_url}/bin/backup.sh" -O "${backup_script}.new"; then
log_error "下载 backup.sh 失败"
log_info "恢复备份..."
[[ -f "${backup_script}.backup" ]] && mv "${backup_script}.backup" "${backup_script}"
exit 1
fi
else
if ! curl -sL "${repo_url}/bin/backup.sh" -o "${backup_script}.new"; then
log_error "下载 backup.sh 失败"
log_info "恢复备份..."
[[ -f "${backup_script}.backup" ]] && mv "${backup_script}.backup" "${backup_script}"
exit 1
fi
fi
# 下载新版本 cleanup.sh
log_info "下载最新 cleanup.sh..."
if command -v wget &> /dev/null; then
if ! wget -q "${repo_url}/bin/cleanup.sh" -O "${cleanup_script}.new"; then
log_error "下载 cleanup.sh 失败"
log_info "恢复备份..."
[[ -f "${backup_script}.backup" ]] && mv "${backup_script}.backup" "${backup_script}"
[[ -f "${cleanup_script}.backup" ]] && mv "${cleanup_script}.backup" "${cleanup_script}"
rm -f "${backup_script}.new"
exit 1
fi
else
if ! curl -sL "${repo_url}/bin/cleanup.sh" -o "${cleanup_script}.new"; then
log_error "下载 cleanup.sh 失败"
log_info "恢复备份..."
[[ -f "${backup_script}.backup" ]] && mv "${backup_script}.backup" "${backup_script}"
[[ -f "${cleanup_script}.backup" ]] && mv "${cleanup_script}.backup" "${cleanup_script}"
rm -f "${backup_script}.new"
exit 1
fi
fi
# 替换为新版本
log_info "安装新版本..."
mv "${backup_script}.new" "${backup_script}"
mv "${cleanup_script}.new" "${cleanup_script}"
chmod +x "${backup_script}"
chmod +x "${cleanup_script}"
# 清理备份文件
rm -f "${backup_script}.backup"
rm -f "${cleanup_script}.backup"
log_info "=========================================="
log_info "更新完成!"
log_info "=========================================="
}
###############################################################################
# 显示帮助信息
###############################################################################
show_help() {
cat << EOF
Docker Backup - Docker 数据备份工具
使用方法:
docker-backup [命令]
命令:
(无参数) 执行备份任务
update 从远程仓库更新脚本到最新版本
help 显示此帮助信息
示例:
docker-backup # 执行备份
docker-backup update # 更新脚本
sudo docker-backup update # 以 root 权限更新脚本
配置文件:
/etc/docker-backup/config.yml
日志文件:
配置文件中 logging.log_file 指定的路径
默认: /var/log/docker-backup.log
项目地址:
https://gitea.bcde.io/wangdefa/docker-backup
EOF
}
############################################################################### ###############################################################################
# 主函数 # 主函数
############################################################################### ###############################################################################
main() { run_backup() {
log_info "==========================================" log_info "=========================================="
log_info "Docker Backup 开始执行" log_info "Docker Backup 开始执行"
log_info "==========================================" log_info "=========================================="
@@ -429,11 +660,14 @@ main() {
# 备份文件夹 # 备份文件夹
local folders_tar=$(backup_folders) local folders_tar=$(backup_folders)
# 备份单个文件
local files_tar=$(backup_files)
# 备份 MySQL # 备份 MySQL
local mysql_dump=$(backup_mysql) local mysql_dump=$(backup_mysql)
# 合并备份 # 合并备份
local final_backup=$(merge_backups "${folders_tar}" "${mysql_dump}") local final_backup=$(merge_backups "${folders_tar}" "${files_tar}" "${mysql_dump}")
# 清理旧备份 # 清理旧备份
cleanup_old_backups cleanup_old_backups
@@ -444,5 +678,31 @@ main() {
log_info "==========================================" log_info "=========================================="
} }
###############################################################################
# 参数解析
###############################################################################
main() {
local command="${1:-}"
case "${command}" in
update)
update_script
;;
help|--help|-h)
show_help
;;
"")
run_backup
;;
*)
log_error "未知命令: ${command}"
echo ""
show_help
exit 1
;;
esac
}
# 执行主函数 # 执行主函数
main "$@" main "$@"

View File

@@ -36,6 +36,17 @@ folders:
- "*/.git" - "*/.git"
- "*/node_modules" - "*/node_modules"
# 单文件备份配置
files:
# 是否启用单文件备份
enabled: true
# 需要备份的文件列表(支持多个)
sources:
- "/etc/docker-backup/config.yml"
- "/etc/nginx/nginx.conf"
- "/opt/app/.env"
# MySQL 数据库备份配置 # MySQL 数据库备份配置
mysql: mysql:
# 是否启用 MySQL 备份 # 是否启用 MySQL 备份