feat: 优化

这个提交包含在:
HA
2026-04-27 00:00:42 +08:00
父节点 99c9c69862
当前提交 0d103b931d

查看文件

@@ -562,12 +562,16 @@ smb_retention_smbclient() {
else else
cutoff=$(date -d "-${COMMON_RETENTION_DAYS} days" +%s) cutoff=$(date -d "-${COMMON_RETENTION_DAYS} days" +%s)
fi fi
log "清理远端早于 ${COMMON_RETENTION_DAYS} 天的备份目录" log "清理远端早于 ${COMMON_RETENTION_DAYS} 天的备份目录cutoff=$(date -r "$cutoff" 2>/dev/null || date -d "@$cutoff" 2>/dev/null)"
dbg "cutoff=$cutoff ($(date -r "$cutoff" 2>/dev/null || date -d "@$cutoff" 2>/dev/null))" dbg "cutoff=$cutoff"
# 先把符合命名规范的目录列出来;用 process substitution 而不是管道,避免 while 跑在子 shell 中导致计数器丢失
# smbclient ls 输出形如: name FLAGS size weekday mon dd hh:mm:ss yyyy # smbclient ls 输出形如: name FLAGS size weekday mon dd hh:mm:ss yyyy
# 目录会带 D 标志;这里直接以名字模式 + D 标志双重匹配,减少误删风险。 # 目录会带 D 标志;这里直接以名字模式 + D 标志双重匹配,减少误删风险。
echo "$listing" | awk '$2 ~ /D/ {print $1}' | grep -E "^${COMMON_ARCHIVE_PREFIX}-[0-9]{8}-[0-9]{6}\$" | while read -r dir; do local scanned=0 deleted=0 kept=0 failed=0 dir
while read -r dir; do
[[ -z "$dir" ]] && continue
scanned=$((scanned+1))
local d="${dir#${COMMON_ARCHIVE_PREFIX}-}" local d="${dir#${COMMON_ARCHIVE_PREFIX}-}"
d="${d%%-*}" # YYYYmmdd d="${d%%-*}" # YYYYmmdd
local t="${dir##*-}" # HHMMSS local t="${dir##*-}" # HHMMSS
@@ -578,14 +582,28 @@ smb_retention_smbclient() {
else else
ftime=$(date -d "$iso" +%s) ftime=$(date -d "$iso" +%s)
fi fi
dbg " 远端目录 $dir -> ftime=$ftime" dbg " 远端目录 $dir -> ftime=$ftime ($iso)"
if [[ "$ftime" -lt "$cutoff" ]]; then if [[ "$ftime" -lt "$cutoff" ]]; then
log "删除远端旧备份目录:$dir" log " 删除:$dir(备份时间 $iso"
# 先清空目录内文件,再 rmdir # 先清空目录内文件,再 rmdir
smbclient "${args[@]}" -D "${SMB_PATH:-/}/${dir}" -c "prompt OFF; mask *; del *" >/dev/null 2>&1 smbclient "${args[@]}" -D "${SMB_PATH:-/}/${dir}" -c "prompt OFF; mask *; del *" >/dev/null 2>&1
smbclient "${args[@]}" -D "${SMB_PATH:-/}" -c "rmdir \"${dir}\"" >/dev/null 2>&1 || warn "rmdir 失败:$dir" if smbclient "${args[@]}" -D "${SMB_PATH:-/}" -c "rmdir \"${dir}\"" >/dev/null 2>&1; then
deleted=$((deleted+1))
else
warn " rmdir 失败:$dir"
failed=$((failed+1))
fi
else
dbg " 保留:$dir(备份时间 $iso,未到保留期)"
kept=$((kept+1))
fi
done < <(echo "$listing" | awk '$2 ~ /D/ {print $1}' | grep -E "^${COMMON_ARCHIVE_PREFIX}-[0-9]{8}-[0-9]{6}\$")
if [[ $scanned -eq 0 ]]; then
log "远端无符合命名规范的备份目录,无需清理"
else
log "清理完成:扫描 ${scanned} 个目录,删除 ${deleted},保留 ${kept}$([[ $failed -gt 0 ]] && echo ",失败 ${failed}")"
fi fi
done
} }
run_smb() { run_smb() {
@@ -705,11 +723,15 @@ rclone_retention() {
else else
cutoff=$(date -d "-${COMMON_RETENTION_DAYS} days" +%s) cutoff=$(date -d "-${COMMON_RETENTION_DAYS} days" +%s)
fi fi
log "清理远端早于 ${COMMON_RETENTION_DAYS} 天的备份目录" log "清理远端早于 ${COMMON_RETENTION_DAYS} 天的备份目录cutoff=$(date -r "$cutoff" 2>/dev/null || date -d "@$cutoff" 2>/dev/null)"
dbg "cutoff=$cutoff parent=$parent" dbg "cutoff=$cutoff parent=$parent"
# rclone lsf --dirs-only 输出形如 "name/",去掉尾随斜杠后做名字匹配 # rclone lsf --dirs-only 输出形如 "name/",去掉尾随斜杠后做名字匹配
echo "$listing" | sed 's:/$::' | grep -E "^${COMMON_ARCHIVE_PREFIX}-[0-9]{8}-[0-9]{6}\$" | while read -r dir; do # 用 process substitution 而非管道,保证 while 在当前 shell 中跑,计数器不丢
local scanned=0 deleted=0 kept=0 failed=0 dir
while read -r dir; do
[[ -z "$dir" ]] && continue
scanned=$((scanned+1))
local d="${dir#${COMMON_ARCHIVE_PREFIX}-}" local d="${dir#${COMMON_ARCHIVE_PREFIX}-}"
d="${d%%-*}" # YYYYmmdd d="${d%%-*}" # YYYYmmdd
local t="${dir##*-}" # HHMMSS local t="${dir##*-}" # HHMMSS
@@ -720,14 +742,26 @@ rclone_retention() {
else else
ftime=$(date -d "$iso" +%s) ftime=$(date -d "$iso" +%s)
fi fi
dbg " 远端目录 $dir -> ftime=$ftime" dbg " 远端目录 $dir -> ftime=$ftime ($iso)"
if [[ "$ftime" -lt "$cutoff" ]]; then if [[ "$ftime" -lt "$cutoff" ]]; then
log "删除远端旧备份目录:$dir" log " 删除:${parent}/${dir}(备份时间 $iso"
if ! rclone_cmd purge "${parent}/${dir}" >/dev/null 2>&1; then if rclone_cmd purge "${parent}/${dir}" >/dev/null 2>&1; then
warn "purge 失败:$dir" deleted=$((deleted+1))
else
warn " purge 失败:$dir"
failed=$((failed+1))
fi fi
else
dbg " 保留:$dir(备份时间 $iso,未到保留期)"
kept=$((kept+1))
fi
done < <(echo "$listing" | sed 's:/$::' | grep -E "^${COMMON_ARCHIVE_PREFIX}-[0-9]{8}-[0-9]{6}\$")
if [[ $scanned -eq 0 ]]; then
log "远端无符合命名规范的备份目录,无需清理"
else
log "清理完成:扫描 ${scanned} 个目录,删除 ${deleted},保留 ${kept}$([[ $failed -gt 0 ]] && echo ",失败 ${failed}")"
fi fi
done
} }
run_rclone() { run_rclone() {