feat(backup): 实现 keep_count 清理策略和自动更新功能

- 添加 keep_count 配置读取,支持按数量保留备份
- 实现基于文件数量的清理逻辑,保留最新的 N 个备份文件
- 添加 docker-backup update 自动更新命令,从远程仓库拉取最新版本
- 添加 docker-backup help 帮助信息,显示完整使用说明
- 优化清理策略:优先使用 keep_days,其次使用 keep_count
- 添加版本备份和错误恢复机制,确保更新安全
This commit is contained in:
Wang Defa
2025-12-25 17:23:43 +08:00
parent 46a0ade8ba
commit 0459136442

View File

@@ -146,6 +146,7 @@ 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}")
@@ -394,24 +395,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 "=========================================="
@@ -444,5 +601,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 "$@"