feat(backup): 实现 keep_count 清理策略和自动更新功能
- 添加 keep_count 配置读取,支持按数量保留备份 - 实现基于文件数量的清理逻辑,保留最新的 N 个备份文件 - 添加 docker-backup update 自动更新命令,从远程仓库拉取最新版本 - 添加 docker-backup help 帮助信息,显示完整使用说明 - 优化清理策略:优先使用 keep_days,其次使用 keep_count - 添加版本备份和错误恢复机制,确保更新安全
This commit is contained in:
187
bin/backup.sh
187
bin/backup.sh
@@ -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 "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user