File size: 10,000 Bytes
13ad5f7 636a8bc b10884e 636a8bc b10884e 636a8bc b10884e 13ad5f7 636a8bc b10884e 636a8bc b10884e 636a8bc b10884e 636a8bc b10884e 13ad5f7 b10884e 13ad5f7 636a8bc 13ad5f7 636a8bc 13ad5f7 636a8bc 13ad5f7 636a8bc 13ad5f7 |
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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
#!/bin/bash
# 检查必要的环境变量
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
echo "缺少必要的环境变量 WEBDAV_URL、WEBDAV_USERNAME 或 WEBDAV_PASSWORD"
exit 1
fi
if [ -z "$HF_TOKEN" ] || [ -z "$DATASET_ID" ]; then
echo "缺少必要的环境变量 HF_TOKEN 或 DATASET_ID"
exit 1
fi
# 创建数据目录
mkdir -p ./data
# 创建 HuggingFace 同步脚本
cat > /tmp/hf_sync.py << 'EOL'
from huggingface_hub import HfApi
import sys
import os
def manage_backups(api, repo_id, max_files=50):
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset")
backup_files = [f for f in files if f.startswith('webui_backup_') and f.endswith('.db')]
backup_files.sort()
if len(backup_files) >= max_files:
files_to_delete = backup_files[:(len(backup_files) - max_files + 1)]
for file_to_delete in files_to_delete:
try:
api.delete_file(path_in_repo=file_to_delete, repo_id=repo_id, repo_type="dataset")
print(f'已删除旧备份: {file_to_delete}')
except Exception as e:
print(f'删除 {file_to_delete} 时出错: {str(e)}')
def upload_backup(file_path, file_name, token, repo_id):
api = HfApi(token=token)
try:
api.upload_file(
path_or_fileobj=file_path,
path_in_repo=file_name,
repo_id=repo_id,
repo_type="dataset"
)
print(f"成功上传 {file_name}")
manage_backups(api, repo_id)
except Exception as e:
print(f"文件上传出错: {str(e)}")
# 下载最新备份
def download_latest_backup(token, repo_id):
try:
api = HfApi(token=token)
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset")
backup_files = [f for f in files if f.startswith('webui_backup_') and f.endswith('.db')]
if not backup_files:
print("未找到备份文件")
return False
latest_backup = sorted(backup_files)[-1]
filepath = api.hf_hub_download(
repo_id=repo_id,
filename=latest_backup,
repo_type="dataset"
)
if filepath and os.path.exists(filepath):
os.makedirs('./data', exist_ok=True)
os.system(f'cp "{filepath}" ./data/webui.db')
print(f"成功从 {latest_backup} 恢复备份")
return True
return False
except Exception as e:
print(f"下载备份时出错: {str(e)}")
return False
if __name__ == "__main__":
action = sys.argv[1]
token = sys.argv[2]
repo_id = sys.argv[3]
if action == "upload":
file_path = sys.argv[4]
file_name = sys.argv[5]
upload_backup(file_path, file_name, token, repo_id)
elif action == "download":
download_latest_backup(token, repo_id)
EOL
# 首次启动时的数据恢复策略
echo "开始初始化数据恢复..."
# 打印 WebDAV 信息(隐藏密码)
echo "WebDAV URL: $WEBDAV_URL"
echo "WebDAV 用户名: $WEBDAV_USERNAME"
masked_password=$(echo $WEBDAV_PASSWORD | sed 's/./*/g')
echo "WebDAV 密码: $masked_password"
# 首先尝试从 WebDAV 恢复最新文件
echo "正在尝试从 WebDAV 获取文件列表..."
echo "PROPFIND 请求: $WEBDAV_URL/openwebui/"
# 获取并打印 WebDAV 目录内容
webdav_list_output=$(curl -v -X PROPFIND --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -H "Depth: 1" "$WEBDAV_URL/openwebui/" 2>&1)
echo "WebDAV 目录内容响应:"
echo "$webdav_list_output"
# 获取 WebDAV 目录中的文件列表并找出最新的备份文件
webdav_files=$(echo "$webdav_list_output" | grep -o '<d:href>[^<]*webui_[0-9][0-9]-[0-9][0-9]\.db</d:href>' | sed 's/<d:href>//g' | sed 's/<\/d:href>//g')
if [ -n "$webdav_files" ]; then
# 找出最新的文件 (按文件名排序,取最后一个)
latest_file=$(echo "$webdav_files" | sort | tail -n 1)
echo "找到最新的 WebDAV 备份文件: $latest_file"
# 构建并打印完整下载链接
download_url="$WEBDAV_URL$latest_file"
echo "下载 URL: $download_url"
# 下载最新文件
curl -v -L --fail --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$download_url" -o "./data/webui.db" && {
echo "成功从 WebDAV 下载最新数据库文件: $latest_file"
# 上传到 HuggingFace
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="webui_backup_${timestamp}.db"
cp ./data/webui.db "/tmp/${backup_file}"
echo "正在上传初始备份到 HuggingFace..."
python3 /tmp/hf_sync.py upload "${HF_TOKEN}" "${DATASET_ID}" "/tmp/${backup_file}" "${backup_file}"
rm -f "/tmp/${backup_file}"
} || {
echo "从 WebDAV 下载最新文件失败,尝试下载 WebDAV 的 webui.db..."
# 打印 webui.db 下载链接
main_db_url="$WEBDAV_URL/openwebui/webui.db"
echo "尝试下载主数据库文件 URL: $main_db_url"
curl -v -L --fail --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$main_db_url" -o "./data/webui.db" && {
echo "成功从 WebDAV 下载主数据库文件"
# 上传到 HuggingFace
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="webui_backup_${timestamp}.db"
cp ./data/webui.db "/tmp/${backup_file}"
echo "正在上传初始备份到 HuggingFace..."
python3 /tmp/hf_sync.py upload "${HF_TOKEN}" "${DATASET_ID}" "/tmp/${backup_file}" "${backup_file}"
rm -f "/tmp/${backup_file}"
} || {
echo "从 WebDAV 下载失败,尝试从 HuggingFace 恢复..."
python3 /tmp/hf_sync.py download "${HF_TOKEN}" "${DATASET_ID}" || {
echo "所有恢复方式均失败,将使用空数据库开始"
}
}
}
else
echo "WebDAV 中没有找到符合格式的备份文件,尝试下载 webui.db..."
# 打印 webui.db 下载链接
main_db_url="$WEBDAV_URL/openwebui/webui.db"
echo "尝试下载主数据库文件 URL: $main_db_url"
curl -v -L --fail --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$main_db_url" -o "./data/webui.db" && {
echo "成功从 WebDAV 下载主数据库文件"
# 上传到 HuggingFace
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="webui_backup_${timestamp}.db"
cp ./data/webui.db "/tmp/${backup_file}"
echo "正在上传初始备份到 HuggingFace..."
python3 /tmp/hf_sync.py upload "${HF_TOKEN}" "${DATASET_ID}" "/tmp/${backup_file}" "${backup_file}"
rm -f "/tmp/${backup_file}"
} || {
echo "从 WebDAV 下载失败,尝试从 HuggingFace 恢复..."
python3 /tmp/hf_sync.py download "${HF_TOKEN}" "${DATASET_ID}" || {
echo "所有恢复方式均失败,将使用空数据库开始"
}
}
fi
# 定义 WebDAV 同步函数
webdav_sync() {
SYNC_INTERVAL=${SYNC_INTERVAL:-7200} # 默认间隔时间为 7200 秒
echo "WebDAV 同步进程启动,等待 ${SYNC_INTERVAL} 秒后开始同步..."
sleep $SYNC_INTERVAL
while true; do
echo "开始 WebDAV 同步 $(date)"
# 检查数据库文件是否存在
if [ -f "./data/webui.db" ]; then
# 生成当前时间的文件名
FILENAME="webui_$(date +'%m-%d_%H%M').db"
echo "同步到 WebDAV..."
upload_url="$WEBDAV_URL/openwebui/$FILENAME"
echo "上传 URL: $upload_url"
# 上传以日期命名的数据库文件
curl -v -L -T "./data/webui.db" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$upload_url" && {
echo "WebDAV 上传成功: $FILENAME"
# 覆盖Webdav目录下默认的webui.db文件
main_file_url="$WEBDAV_URL/openwebui/webui.db"
echo "更新主文件 URL: $main_file_url"
curl -v -L -T "./data/webui.db" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$main_file_url" && {
echo "WebDAV 更新主文件成功"
} || {
echo "WebDAV 更新主文件失败"
}
} || {
echo "WebDAV 上传失败,等待重试..."
sleep 10
echo "重试上传 URL: $upload_url"
curl -v -L -T "./data/webui.db" --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$upload_url" || {
echo "重试失败,放弃上传。"
}
}
else
echo "未找到 webui.db 文件,跳过 WebDAV 同步"
fi
# 等待下一次同步间隔
echo "WebDAV 同步完成,下次同步将在 ${SYNC_INTERVAL} 秒后进行..."
sleep $SYNC_INTERVAL
done
}
# 定义 HuggingFace 同步函数
hf_sync() {
SYNC_INTERVAL=${SYNC_INTERVAL:-7200}
echo "HuggingFace 同步进程启动,等待 ${SYNC_INTERVAL} 秒后开始同步..."
sleep $(($SYNC_INTERVAL / 2)) # 错开与 WebDAV 同步的时间
while true; do
echo "开始 HuggingFace 同步 $(date)"
if [ -f "./data/webui.db" ]; then
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="webui_backup_${timestamp}.db"
# 复制数据库文件
cp ./data/webui.db "/tmp/${backup_file}"
echo "正在上传备份到 HuggingFace..."
python3 /tmp/hf_sync.py upload "${HF_TOKEN}" "${DATASET_ID}" "/tmp/${backup_file}" "${backup_file}"
rm -f "/tmp/${backup_file}"
else
echo "数据库文件不存在,跳过 HuggingFace 同步"
fi
echo "HuggingFace 同步完成,下次同步将在 ${SYNC_INTERVAL} 秒后进行..."
sleep $SYNC_INTERVAL
done
}
# 后台启动同步进程
webdav_sync &
hf_sync &
|