feat: 修改逻辑
这个提交包含在:
@@ -27,7 +27,7 @@ CONF_FILE="${SCRIPT_DIR}/backup.conf"
|
||||
# ---- 默认值 ----
|
||||
# 公共配置(统一以 COMMON_ 前缀,与 backup.conf 一致)
|
||||
COMMON_SOURCE_PATHS=""
|
||||
COMMON_TMP_DIR="/tmp/backup"
|
||||
COMMON_TMP_DIR="/tmp/backup_script"
|
||||
COMMON_ARCHIVE_PREFIX="backup"
|
||||
COMMON_CLEAN_LOCAL="true"
|
||||
COMMON_RETENTION_DAYS=0
|
||||
@@ -79,7 +79,7 @@ Methods:
|
||||
Common options:
|
||||
-C, --config FILE 指定配置文件路径(默认:脚本所在目录下 backup.conf)
|
||||
-s, --source PATHS 要备份的源路径,多个用空格分隔,需引号包裹
|
||||
-t, --tmp-dir DIR 本地临时目录(默认:/tmp/backup)
|
||||
-t, --tmp-dir DIR 本地临时目录(默认:/tmp/backup_script)
|
||||
-p, --prefix NAME 归档文件名前缀(默认:backup)
|
||||
--keep-local 上传后保留本地归档
|
||||
--retention DAYS 远端保留天数,0 表示不清理
|
||||
@@ -424,17 +424,34 @@ create_archive() {
|
||||
}
|
||||
|
||||
cleanup_local() {
|
||||
dbg "cleanup_local: COMMON_CLEAN_LOCAL=$COMMON_CLEAN_LOCAL 文件数=${#ARCHIVE_FILES[@]}"
|
||||
dbg "cleanup_local: COMMON_CLEAN_LOCAL=$COMMON_CLEAN_LOCAL COMMON_TMP_DIR=$COMMON_TMP_DIR PREFIX=$COMMON_ARCHIVE_PREFIX"
|
||||
if [[ "$COMMON_CLEAN_LOCAL" != "true" ]]; then
|
||||
dbg "cleanup_local: 跳过删除"
|
||||
return 0
|
||||
fi
|
||||
local p
|
||||
for p in "${ARCHIVE_FILES[@]}"; do
|
||||
if [[ -f "$p" ]]; then
|
||||
rm -f "$p" && log "已删除本地:$p"
|
||||
fi
|
||||
# 安全栅栏:必备字段不能为空,避免出现 rm -rf /* 这类灾难
|
||||
if [[ -z "$COMMON_TMP_DIR" || -z "$COMMON_ARCHIVE_PREFIX" ]]; then
|
||||
warn "COMMON_TMP_DIR 或 COMMON_ARCHIVE_PREFIX 为空,拒绝清理"
|
||||
return 0
|
||||
fi
|
||||
if [[ ! -d "$COMMON_TMP_DIR" ]]; then
|
||||
dbg "cleanup_local: 目录不存在,跳过"
|
||||
return 0
|
||||
fi
|
||||
# 仅清理所有以 COMMON_ARCHIVE_PREFIX 开头的文件/目录。
|
||||
# 这样既能带走本次的归档/分卷/sha,也能扫掉上次失败遗留(同样以该前缀开头)的
|
||||
# 中间产物(如 *.tar.gz、*.tar.gz.split-tmp.* 等),同时不会误伤同目录下的其它文件。
|
||||
local count=0 p
|
||||
shopt -s nullglob
|
||||
for p in "${COMMON_TMP_DIR%/}/${COMMON_ARCHIVE_PREFIX}"*; do
|
||||
rm -rf -- "$p" && count=$((count+1))
|
||||
done
|
||||
shopt -u nullglob
|
||||
if [[ $count -gt 0 ]]; then
|
||||
log "已清理本地以 \"${COMMON_ARCHIVE_PREFIX}\" 开头的文件/目录 ${count} 项(位于 ${COMMON_TMP_DIR})"
|
||||
else
|
||||
dbg "cleanup_local: 没有匹配 ${COMMON_ARCHIVE_PREFIX}* 的文件"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- SMB ----------
|
||||
@@ -701,9 +718,6 @@ rclone_upload() {
|
||||
done
|
||||
ok "已上传全部 ${#ARCHIVE_FILES[@]} 个文件到 ${remote_dir}/"
|
||||
|
||||
# 远端 SHA256 校验:拉取远端 hash,与本地 .sha256 清单比对
|
||||
rclone_verify_remote "$remote_dir" || return 1
|
||||
|
||||
if [[ "$COMMON_RETENTION_DAYS" -gt 0 ]]; then
|
||||
rclone_retention
|
||||
else
|
||||
@@ -711,49 +725,6 @@ rclone_upload() {
|
||||
fi
|
||||
}
|
||||
|
||||
rclone_verify_remote() {
|
||||
local remote_dir="$1"
|
||||
local sha_local
|
||||
# 在 ARCHIVE_FILES 中找到 .sha256 清单(cleanup 之前)
|
||||
for f in "${ARCHIVE_FILES[@]}"; do
|
||||
if [[ "$f" == *.sha256 ]]; then sha_local="$f"; break; fi
|
||||
done
|
||||
if [[ -z "$sha_local" || ! -f "$sha_local" ]]; then
|
||||
warn "未找到本地 SHA256 清单,跳过远端校验"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "远端 SHA256 校验:${remote_dir}/"
|
||||
local remote_sha
|
||||
remote_sha="$(rclone_cmd hashsum SHA256 "$remote_dir" 2>/dev/null)" || {
|
||||
err "rclone hashsum 执行失败(远端可能不支持 SHA256,可手动下载后用 sha256sum -c 校验)"
|
||||
return 1
|
||||
}
|
||||
dbg "远端 hash 输出: $remote_sha"
|
||||
|
||||
# 本地清单格式: "<hash> <filename>";远端 rclone hashsum 输出同样格式但顺序可能不同
|
||||
# 逐行比对:以文件名为 key,hash 必须一致
|
||||
local fname expect actual
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" ]] && continue
|
||||
expect="${line%% *}"
|
||||
fname="${line##* }"
|
||||
# 跳过清单文件自身(不会出现在 ARCHIVE 主体里,但保险)
|
||||
[[ "$fname" == "$(basename "$sha_local")" ]] && continue
|
||||
actual="$(echo "$remote_sha" | awk -v f="$fname" '$2==f{print $1; exit}')"
|
||||
if [[ -z "$actual" ]]; then
|
||||
err "远端缺少文件:$fname"
|
||||
return 1
|
||||
fi
|
||||
if [[ "$expect" != "$actual" ]]; then
|
||||
err "远端 SHA256 不匹配:$fname (本地=$expect 远端=$actual)"
|
||||
return 1
|
||||
fi
|
||||
dbg " 校验通过:$fname"
|
||||
done < "$sha_local"
|
||||
ok "远端 SHA256 校验全部通过"
|
||||
}
|
||||
|
||||
rclone_retention() {
|
||||
dbg "rclone_retention: COMMON_RETENTION_DAYS=$COMMON_RETENTION_DAYS"
|
||||
local parent="${RCLONE_REMOTE}:${RCLONE_PATH%/}"
|
||||
|
||||
在新工单中引用
屏蔽一个用户