Refactor backup config and Telegram notifications

This commit is contained in:
Codex
2026-03-16 17:30:55 +08:00
parent 51c8c37c69
commit d4b69f10f9
8 changed files with 293 additions and 254 deletions
Regular → Executable
+8 -63
View File
@@ -2,7 +2,7 @@
# 清理 OBS 历史备份:按文件名前缀与日期,仅保留最近 N 天
# - 从同目录 env.conf 加载配置;支持 --retain-days / --prefix 覆盖
# - 删除匹配 backup_YYYYmmdd_HHMMSS.tar.gz[.gpg] 以及对应 .sha256
# - 记录日志并发送 Telegram 摘要Markdown
# - 记录日志并发送 Telegram 摘要
# 退出码:0 成功;2 配置缺失/依赖缺失;6 清理失败
set -Eeuo pipefail
@@ -21,64 +21,15 @@ log() {
echo "$line" | tee -a "${LOG_FILE:-./backup.log}"
}
#############################
# Telegram 通知(Markdown
#############################
send_telegram() {
local status="${1-}" # success | error
local reason="${2-}" # 错误原因(可选)
local error_log="${3-}" # 详细错误日志(可选)
if [[ -z "${TG_BOT_TOKEN:-}" || -z "${TG_USER_ID:-}" ]]; then
log "INFO" "未配置Telegram通知,跳过发送"
return 0
fi
local api="https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage"
local current_date; current_date="$(date +'%Y-%m-%d %H:%M:%S')"
local message
if [[ "$status" == "success" ]]; then
message="*清理完成通知*\n\n"
message+="主机:${LABEL}\n"
message+="时间:${current_date}\n"
message+="前缀:obs://${OBS_BUCKET}/${TARGET_PREFIX}\n"
message+="保留天数:${RETAIN_DAYS}\n"
message+="保留对象数:${#TO_KEEP[@]}\n"
message+="删除成功:${DEL_OK}\n"
message+="删除失败:${DEL_FAIL}"
else
message="*清理失败通知*\n\n${LABEL} 清理任务失败!"
if [[ -n "$reason" ]]; then
message+="\n原因:${reason}"
fi
if [[ -n "$error_log" ]]; then
message+="\n错误日志:\n\`\`\`${error_log}\`\`\`"
fi
fi
# 转换换行符 \n -> %0A
local encoded_message=${message//\\n/%0A}
local response
response="$(curl -sS -X POST "$api" \
-d "chat_id=${TG_USER_ID}" \
-d "parse_mode=Markdown" \
-d "disable_web_page_preview=true" \
-d "text=${encoded_message}" 2>&1 || true)"
if echo "$response" | grep -q '"ok":true'; then
log "INFO" "Telegram通知发送成功"
else
log "WARN" "Telegram通知发送失败: $response"
fi
}
# shellcheck disable=SC1091
source "${SCRIPT_DIR}/lib/telegram.sh"
on_error() {
local exit_code=$?
local tail_log
log "ERROR" "清理异常退出(exit=${exit_code})"
local tail_log; tail_log="$(tail -n 80 "${LOG_FILE:-./backup.log}" 2>/dev/null || true)"
send_telegram "error" "脚本异常退出(exit=${exit_code}" "$tail_log"
tail_log="$(tail -n 80 "${LOG_FILE:-./backup.log}" 2>/dev/null || true)"
tg_clean_error "$LABEL" "$(date +'%Y-%m-%d %H:%M:%S')" "脚本异常退出(exit=${exit_code}" "$tail_log"
exit "$exit_code"
}
trap on_error ERR
@@ -102,7 +53,6 @@ source "$CONF_FILE"
need_cmd obsutil
# 严格按要求:配置文件位于 ~/.obsutilconfig
OBSUTIL_CONFIG_PATH="${HOME}/.obsutilconfig"
if [[ ! -f "$OBSUTIL_CONFIG_PATH" ]]; then
log "ERROR" "未检测到 obsutil 配置文件:${OBSUTIL_CONFIG_PATH}"
@@ -110,7 +60,6 @@ if [[ ! -f "$OBSUTIL_CONFIG_PATH" ]]; then
exit 2
fi
# 覆盖参数
CLI_RETAIN=""
CLI_PREFIX=""
usage() {
@@ -134,15 +83,13 @@ if [[ -n "$CLI_PREFIX" ]]; then TARGET_PREFIX="${TARGET_PREFIX}${CLI_PREFIX%/}/"
log "INFO" "开始清理:bucket=${OBS_BUCKET} prefix=${TARGET_PREFIX} 保留最近 ${RETAIN_DAYS}"
# 计算截止日期(N 天前零点,格式 YYYYmmdd)
CUTOFF_DATE="$(date -d "-${RETAIN_DAYS} days" +%Y%m%d)"
# 列举对象
LIST_OUT="$(mktemp)"
if ! obsutil ls "obs://${OBS_BUCKET}/${TARGET_PREFIX}" >"$LIST_OUT" 2>/dev/null; then
log "ERROR" "无法列举 obs://${OBS_BUCKET}/${TARGET_PREFIX}"
rm -f "$LIST_OUT"
send_telegram "error" "无法列举 obs://${OBS_BUCKET}/${TARGET_PREFIX}" ""
tg_clean_error "$LABEL" "$(date +'%Y-%m-%d %H:%M:%S')" "无法列举 obs://${OBS_BUCKET}/${TARGET_PREFIX}" ""
exit 6
fi
@@ -167,7 +114,6 @@ for obj in "${OBJECTS[@]}"; do
fi
done
# 去重
if [[ "${#TO_DELETE[@]}" -gt 0 ]]; then
mapfile -t TO_DELETE < <(printf '%s\n' "${TO_DELETE[@]}" | awk '!a[$0]++')
fi
@@ -190,8 +136,7 @@ else
done
fi
# 通知与退出码
send_telegram "success"
tg_clean_success "$LABEL" "$(date +'%Y-%m-%d %H:%M:%S')" "obs://${OBS_BUCKET}/${TARGET_PREFIX}" "${RETAIN_DAYS}" "${#TO_KEEP[@]}" "${DEL_OK}" "${DEL_FAIL}"
if (( DEL_FAIL > 0 )); then
exit 6
fi