File size: 7,470 Bytes
13ad5f7 51af98b 13ad5f7 51af98b 13ad5f7 51af98b 85c4208 51af98b 85c4208 51af98b b10884e 51af98b 7d26d69 51af98b b10884e 13ad5f7 51af98b 7d26d69 51af98b 7d26d69 51af98b 7d26d69 51af98b 85c4208 51af98b 7d26d69 85c4208 51af98b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
#!/bin/bash
# sync_data.sh - 负责数据恢复和启动后台同步任务
# 遇到错误时立即退出(在恢复阶段)
set -e
# --- 配置 ---
# WebDAV 相关环境变量由 Hugging Face Secrets 提供:
# WEBDAV_URL, WEBDAV_USERNAME, WEBDAV_PASSWORD
# Hugging Face 相关环境变量由 Hugging Face Secrets 提供:
# HF_TOKEN, DATASET_ID
WEBDAV_BASE_PATH="openwebui" # WebDAV上的基础目录名
LOCAL_DATA_DIR="./data" # 本地数据存储目录
DB_FILENAME="webui.db" # 数据库文件名
WEBDAV_SYNC_INTERVAL=${WEBDAV_SYNC_INTERVAL:-7200} # WebDAV同步间隔(秒),默认2小时
HF_SYNC_INTERVAL=${HF_SYNC_INTERVAL:-7200} # Hugging Face同步间隔(秒),默认2小时
WEBDAV_CLEANUP_DAYS=7 # WebDAV保留最近多少天的备份
HF_MAX_BACKUPS=50 # Hugging Face保留的最大备份数量 (通过hf_sync.py控制)
# --- 检查环境变量 ---
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
echo "错误:缺少必要的WebDAV环境变量 (WEBDAV_URL, WEBDAV_USERNAME, WEBDAV_PASSWORD)。"
exit 1
fi
if [ -z "$HF_TOKEN" ] || [ -z "$DATASET_ID" ]; then
echo "错误:缺少必要的Hugging Face环境变量 (HF_TOKEN, DATASET_ID)。"
exit 1
fi
# 确保WebDAV URL末尾没有斜杠,方便拼接
WEBDAV_URL=$(echo "$WEBDAV_URL" | sed 's:/*$::')
WEBDAV_FULL_PATH="$WEBDAV_URL/$WEBDAV_BASE_PATH"
# --- 函数定义 ---
# 计算文件MD5哈希
get_file_hash() {
local file_path="$1"
if [ -f "$file_path" ]; then
md5sum "$file_path" | awk '{print $1}'
else
echo "not_found" # 返回特殊值表示文件不存在
fi
}
# --- 初始化和恢复 ---
echo "[恢复] 开始初始化数据恢复流程..."
mkdir -p "$LOCAL_DATA_DIR"
LOCAL_DB_PATH="$LOCAL_DATA_DIR/$DB_FILENAME"
recovered=false
# 1. 尝试从 WebDAV 恢复最新的日期文件
echo "[恢复] 尝试从 WebDAV 恢复 ($WEBDAV_FULL_PATH)..."
# 使用 curl 获取目录列表 (PROPFIND)。注意:解析 XML 可能不稳定
# curl -s -f: 静默模式,遇到HTTP错误时失败退出
webdav_list_output=$(curl -s -f --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X PROPFIND -H "Depth: 1" "$WEBDAV_FULL_PATH/" || echo "WebDAV PROPFIND failed")
if [[ "$webdav_list_output" != "WebDAV PROPFIND failed" ]]; then
# 提取日期格式的文件名 (webui_YYYYMMDD.db)
webdav_files=$(echo "$webdav_list_output" | grep '<d:href>' | sed 's#<d:href>[^<]*/$[^<]*$</d:href>#\1#' | grep -E '^webui_[0-9]{8}\.db$')
if [ -n "$webdav_files" ]; then
latest_webdav_file=$(echo "$webdav_files" | sort -r | head -n 1)
echo "[恢复] 在WebDAV找到最新的日期文件: $latest_webdav_file"
download_url="$WEBDAV_FULL_PATH/$latest_webdav_file"
temp_db_path="${LOCAL_DB_PATH}.webdav.tmp"
echo "[恢复] 尝试下载: $download_url"
if curl -L -f -s -o "$temp_db_path" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$download_url"; then
# 验证下载的文件是否有效(至少非空)
if [ -s "$temp_db_path" ]; then
mv "$temp_db_path" "$LOCAL_DB_PATH"
echo "[恢复] 成功从 WebDAV ($latest_webdav_file) 恢复数据库。"
recovered=true
else
echo "[恢复] WebDAV下载的文件为空或无效,删除临时文件。"
rm -f "$temp_db_path"
fi
else
echo "[恢复] 从 WebDAV 下载 $latest_webdav_file 失败。"
rm -f "$temp_db_path"
fi
else
echo "[恢复] 在WebDAV路径 ($WEBDAV_FULL_PATH/) 未找到符合 'webui_YYYYMMDD.db' 格式的文件。"
# 可选:尝试恢复主文件 webui.db (如果存在)
main_db_url="$WEBDAV_FULL_PATH/$DB_FILENAME"
echo "[恢复] 尝试从WebDAV恢复主文件: $main_db_url"
temp_db_path="${LOCAL_DB_PATH}.webdav_main.tmp"
if curl -L -f -s -o "$temp_db_path" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$main_db_url"; then
if [ -s "$temp_db_path" ]; then
mv "$temp_db_path" "$LOCAL_DB_PATH"
echo "[恢复] 成功从 WebDAV (主文件 $DB_FILENAME) 恢复数据库。"
recovered=true
else
echo "[恢复] WebDAV下载的主文件为空或无效,删除临时文件。"
rm -f "$temp_db_path"
fi
else
echo "[恢复] 从WebDAV下载主文件 $DB_FILENAME 失败。"
rm -f "$temp_db_path"
fi
fi
else
echo "[恢复] 无法访问WebDAV目录 ($WEBDAV_FULL_PATH/)。"
fi
# 2. 如果WebDAV恢复失败,尝试从 Hugging Face 恢复
if [ "$recovered" != true ]; then
echo "[恢复] WebDAV恢复失败或未找到文件,尝试从 Hugging Face ($DATASET_ID) 恢复..."
# 调用 Python 脚本进行下载,传递目标目录
if python3 /app/hf_sync.py download "$HF_TOKEN" "$DATASET_ID" "$LOCAL_DATA_DIR"; then
echo "[恢复] 成功从 Hugging Face 恢复。"
recovered=true
else
echo "[恢复] 从 Hugging Face 恢复也失败了。"
fi
fi
# 3. 如果所有恢复都失败,并且本地数据库文件不存在,则创建空文件
if [ "$recovered" != true ] && [ ! -f "$LOCAL_DB_PATH" ]; then
echo "[恢复] 所有恢复方式均失败,创建空的数据库文件: $LOCAL_DB_PATH"
touch "$LOCAL_DB_PATH"
fi
echo "[恢复] 数据恢复流程结束。"
# --- 后台同步任务 ---
# WebDAV 同步函数
webdav_sync() {
echo "[WebDAV Sync] 后台任务启动,间隔: ${WEBDAV_SYNC_INTERVAL} 秒"
local last_uploaded_hash=""
while true; do
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[WebDAV Sync @ $timestamp] 开始检查..."
if [ -f "$LOCAL_DB_PATH" ]; then
current_hash=$(get_file_hash "$LOCAL_DB_PATH")
echo "[WebDAV Sync @ $timestamp] 本地文件哈希: $current_hash"
if [ "$current_hash" == "$last_uploaded_hash" ]; then
echo "[WebDAV Sync @ $timestamp] 文件未变化,跳过上传。"
else
echo "[WebDAV Sync @ $timestamp] 检测到文件变化或首次运行,准备上传到 WebDAV..."
current_date=$(date +'%Y%m%d')
dated_filename="webui_${current_date}.db"
upload_dated_url="$WEBDAV_FULL_PATH/$dated_filename"
upload_main_url="$WEBDAV_FULL_PATH/$DB_FILENAME"
# 上传带日期的文件
echo "[WebDAV Sync @ $timestamp] 上传日期文件: $upload_dated_url"
if curl -L -f -T "$LOCAL_DB_PATH" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$upload_dated_url"; then
echo "[WebDAV Sync @ $timestamp] 日期文件上传成功: $dated_filename"
# 上传主文件 (覆盖)
echo "[WebDAV Sync @ $timestamp] 更新主文件: $upload_main_url"
if curl -L -f -T "$LOCAL_DB_PATH" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$upload_main_url"; then
echo "[WebDAV Sync @ $timestamp] 主文件更新成功。"
last_uploaded_hash=$current_hash # 只有主文件也成功才更新哈希
else
echo "[WebDAV Sync @ $timestamp] 错误:主文件更新失败!"
# 主文件失败,不更新哈希,下次会
|