Spaces:
Sleeping
Sleeping
| # ================= 配置 ================= | |
| WEBDAV_URL=${WEBDAV_URL%/} | |
| WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-""} | |
| # 处理子路径 | |
| WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH#/} | |
| WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH%/} | |
| if [ -n "$WEBDAV_BACKUP_PATH" ]; then | |
| FULL_WEBDAV_URL="${WEBDAV_URL}/${WEBDAV_BACKUP_PATH}" | |
| else | |
| FULL_WEBDAV_URL="${WEBDAV_URL}" | |
| fi | |
| SYNC_INTERVAL=${SYNC_INTERVAL:-60} | |
| TARGET_FILENAME="accounts.json" | |
| REMOTE_FILENAME="antigravity_accounts.json" | |
| TEMP_DIR="/tmp/backup_temp" | |
| # ======================================= | |
| log() { echo "[Backup] [$(date '+%H:%M:%S')] $1"; } | |
| mkdir -p "$TEMP_DIR" | |
| # 检查环境 | |
| if [[ -z "$WEBDAV_URL" ]]; then | |
| log "未设置 WEBDAV_URL,跳过备份" | |
| exit 0 | |
| fi | |
| if ! command -v curl &> /dev/null; then | |
| apk add --no-cache curl || (apt-get update && apt-get install -y curl) | |
| fi | |
| # === 核心修复:智能寻找真正活跃的文件 === | |
| find_active_file() { | |
| FILE_ROOT="/app/$TARGET_FILENAME" | |
| FILE_DATA="/app/data/$TARGET_FILENAME" | |
| # 获取文件修改时间戳 (如果文件不存在则为0) | |
| TIME_ROOT=$(stat -c %Y "$FILE_ROOT" 2>/dev/null || echo 0) | |
| TIME_DATA=$(stat -c %Y "$FILE_DATA" 2>/dev/null || echo 0) | |
| # 比较哪个文件更新 | |
| if [ "$TIME_ROOT" -gt "$TIME_DATA" ]; then | |
| echo "$FILE_ROOT" | |
| elif [ "$TIME_DATA" -gt 0 ]; then | |
| echo "$FILE_DATA" | |
| else | |
| # 如果都没有,尝试用 find 找 (兼容性兜底) | |
| find /app -name "$TARGET_FILENAME" -type f -not -path "*/node_modules/*" | head -n 1 | |
| fi | |
| } | |
| # === 恢复功能 === | |
| restore() { | |
| log "正在从 WebDAV 恢复备份..." | |
| REMOTE_FILE="$FULL_WEBDAV_URL/$REMOTE_FILENAME" | |
| TEMP_FILE="$TEMP_DIR/restored.json" | |
| HTTP_CODE=$(curl -s -o "$TEMP_FILE" -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$REMOTE_FILE") | |
| if [[ "$HTTP_CODE" == "200" ]] && [ -s "$TEMP_FILE" ]; then | |
| # 恢复策略:只恢复到 /app 根目录 | |
| # 为什么?因为我们确定程序会优先读取根目录,或者在根目录生成 | |
| # 如果程序之前在 data 目录,它找不到 data 里的文件通常会自动回落或重建 | |
| DEST_PATH="/app/$TARGET_FILENAME" | |
| cp "$TEMP_FILE" "$DEST_PATH" | |
| log "✅ 备份已恢复到: $DEST_PATH" | |
| # 只有当 data 目录已经存在时,才顺便放一份进去,但不强求 | |
| if [ -d "/app/data" ]; then | |
| cp "$TEMP_FILE" "/app/data/$TARGET_FILENAME" | |
| fi | |
| else | |
| log "📭 未找到远程备份或文件为空,将以新状态启动" | |
| fi | |
| } | |
| # === 循环备份功能 === | |
| loop() { | |
| log "启动智能增量备份 (间隔: ${SYNC_INTERVAL}秒)" | |
| # 尝试创建远程目录 | |
| if [ -n "$WEBDAV_BACKUP_PATH" ]; then | |
| curl -s -o /dev/null -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X MKCOL "$FULL_WEBDAV_URL/" | |
| fi | |
| while true; do | |
| sleep $SYNC_INTERVAL | |
| # 每次都重新判断哪个文件是最新的 | |
| CURRENT_PATH=$(find_active_file) | |
| if [ -n "$CURRENT_PATH" ] && [ -f "$CURRENT_PATH" ]; then | |
| FILE_SIZE=$(wc -c < "$CURRENT_PATH") | |
| # 只有大于 10 字节才备份 (避免备份空的 []) | |
| if [ "$FILE_SIZE" -gt 10 ]; then | |
| # log "正在备份活跃文件: $CURRENT_PATH (大小: $FILE_SIZE)" | |
| HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "$CURRENT_PATH" "$FULL_WEBDAV_URL/$REMOTE_FILENAME") | |
| if [[ "$HTTP_CODE" != "201" ]] && [[ "$HTTP_CODE" != "204" ]] && [[ "$HTTP_CODE" != "200" ]]; then | |
| log "❌ 上传失败: HTTP $HTTP_CODE" | |
| else | |
| # 成功时不刷屏,静默成功 | |
| : | |
| fi | |
| else | |
| log "⚠️ 文件过小 ($FILE_SIZE bytes),跳过备份以免覆盖数据" | |
| fi | |
| else | |
| log "等待 accounts.json 生成..." | |
| fi | |
| done | |
| } | |
| case "$1" in | |
| "restore") restore ;; | |
| "loop") loop ;; | |
| *) restore; loop ;; | |
| esac |