Spaces:
zx2323
/
Runtime error

File size: 6,810 Bytes
db9bef5
358b846
e703e79
b94e73a
8d932ae
e703e79
 
 
 
 
358b846
96645ff
db9bef5
 
96645ff
 
358b846
e703e79
db9bef5
cef7f31
8d932ae
358b846
 
 
 
 
 
 
 
8d932ae
 
 
358b846
 
 
 
 
 
 
8d932ae
358b846
 
8d932ae
 
 
 
358b846
8d932ae
 
358b846
 
 
8d932ae
358b846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d932ae
5323ea8
8d932ae
358b846
51d3b27
e501092
 
e7c26d6
 
358b846
8d932ae
d36c708
e501092
 
e7c26d6
 
358b846
 
e501092
5323ea8
 
 
 
358b846
8d932ae
 
 
 
5323ea8
8d932ae
5323ea8
8d932ae
5323ea8
8d932ae
 
 
5323ea8
8d932ae
5323ea8
 
8d932ae
5323ea8
 
8d932ae
 
 
 
 
 
 
 
 
 
 
96645ff
 
8d932ae
 
 
db9bef5
358b846
96645ff
8d932ae
db9bef5
8d932ae
fbcd0ca
8d932ae
fbcd0ca
8d932ae
 
fbcd0ca
 
8d932ae
fbcd0ca
 
8d932ae
 
 
 
620fa8f
8d932ae
 
 
 
 
 
 
620fa8f
8d932ae
 
 
 
 
 
fbcd0ca
8d932ae
fbcd0ca
8d932ae
 
 
 
 
 
 
 
 
 
 
 
96645ff
db9bef5
96645ff
358b846
8d932ae
96645ff
 
5bc200e
 
cef7f31
96645ff
8d932ae
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
#!/bin/bash

# 打印环境变量以进行调试
echo "===== Application Startup at $(date '+%Y-%m-%d %H:%M:%S') ====="
echo "===== 应用程序启动于 $(date '+%Y-%m-%d %H:%M:%S') ====="
echo "调试信息:"
echo "WEBDAV_URL: $WEBDAV_URL"
echo "WEBDAV_USERNAME: $WEBDAV_USERNAME"
echo "WEBDAV_PASSWORD: $WEBDAV_PASSWORD"
echo "SYNC_INTERVAL: $SYNC_INTERVAL"

# 检查必要的环境变量
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
    echo "缺少必要的环境变量 WEBDAV_URL、WEBDAV_USERNAME 或 WEBDAV_PASSWORD"
    exit 1
fi

# 创建数据目录
mkdir -p ./data

# 定义上传函数,包含MD5校验和重试逻辑
upload_with_verification() {
    local source_file="$1"
    local target_url="$2"
    local max_retries=3
    local retry_count=0
    local success=false

    while [ $retry_count -lt $max_retries ] && [ "$success" = false ]; do
        # 计算源文件的MD5
        local local_md5=$(md5sum "$source_file" | cut -d' ' -f1)
        echo "本地文件 MD5: $local_md5"

        # 上传文件
        if curl -L -f --connect-timeout 30 --max-time 600 \
            -T "$source_file" \
            --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" \
            "$target_url"; then
            
            # 等待一小段时间确保文件已完全写入服务器
            sleep 5
            
            # 获取远程文件的MD5
            local remote_md5=$(curl -s -L --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" \
                              "$target_url" | md5sum | cut -d' ' -f1)
            echo "远程文件 MD5: $remote_md5"

            if [ "$local_md5" = "$remote_md5" ]; then
                echo "MD5校验通过"
                success=true
                break
            else
                echo "MD5校验失败,准备重试..."
                retry_count=$((retry_count + 1))
                if [ $retry_count -lt $max_retries ]; then
                    echo "等待30秒后进行第 $((retry_count + 1)) 次重试..."
                    sleep 30
                fi
            fi
        else
            echo "上传失败,准备重试..."
            retry_count=$((retry_count + 1))
            if [ $retry_count -lt $max_retries ]; then
                echo "等待30秒后进行第 $((retry_count + 1)) 次重试..."
                sleep 30
            fi
        fi
    done

    if [ "$success" = true ]; then
        return 0
    else
        return 1
    fi
}

# 定义函数:清理 TeraCloud 网盘中的旧文件
clean_remote_files() {
    echo "正在清理 TeraCloud 网盘中的旧文件..."
    # 发送 PROPFIND 请求列出 WebDAV 文件
    RESPONSE=$(curl -s -L -X PROPFIND --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -H "Depth: 1" "$WEBDAV_URL")
    if [ -z "$RESPONSE" ]; then
        echo "无法获取 WebDAV 文件列表"
        return
    fi

    # 使用 xmlstarlet 解析 XML 响应,提取文件名
    FILE_LIST=$(echo "$RESPONSE" | xmlstarlet sel -N d="DAV:" -t -v "//d:href/text()" 2>/dev/null | sed 's|.*/||')
    if [ -z "$FILE_LIST" ]; then
        echo "未找到文件"
        return
    fi

    # 过滤出带有时间戳的文件
    TIMESTAMPED_FILES=$(echo "$FILE_LIST" | grep -E '^webui_[0-9]{2}_[0-9]{2}_[0-9]{4}\.db$')
    if [ -z "$TIMESTAMPED_FILES" ]; then
        echo "未找到带有时间戳的文件,跳过清理"
        return
    fi

    # 按文件名排序
    SORTED_FILES=$(echo "$TIMESTAMPED_FILES" | sort -r)

    # 保留最新的一个文件,删除其他旧文件
    COUNT=0
    for FILE in $SORTED_FILES; do
        COUNT=$((COUNT + 1))
        if [ $COUNT -gt 1 ]; then
            echo "删除旧文件: $FILE"
            curl -X DELETE --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$WEBDAV_URL/$FILE" || {
                echo "删除失败: $FILE"
            }
        else
            echo "保留最新文件: $FILE"
        fi
    done
    echo "TeraCloud 网盘清理完成"
}

# 在第一次运行时清理 TeraCloud 网盘中的旧文件
clean_remote_files

# 从 WebDAV 下载 webui.db 文件
echo "正在从 WebDAV 下载数据库文件..."
if ! curl -L -f --user "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "$WEBDAV_URL/webui.db" -o "./data/webui.db"; then
    echo "下载失败,脚本退出"
    exit 1
fi
echo "下载成功"

# 定义同步函数
sync_data() {
    # 首次等待同步间隔
    SYNC_INTERVAL=${SYNC_INTERVAL:-7200}
    echo "初始下载完成,等待 ${SYNC_INTERVAL} 秒后开始同步..."
    sleep $SYNC_INTERVAL

    while true; do
        echo "正在开始同步"
        if [ -f "./data/webui.db" ]; then
            # 检查是否安装了 sqlite3 命令,如果安装了,执行 WAL checkpoint
            if command -v sqlite3 &> /dev/null; then
                echo "执行 SQLite WAL checkpoint 以确保数据一致性..."
                sqlite3 "./data/webui.db" "PRAGMA wal_checkpoint(TRUNCATE);"
            else
                echo "未找到 sqlite3 命令,跳过 SQLite WAL checkpoint."
            fi

            # 创建临时副本以避免文件写入冲突
            TIMESTAMP=$(date +%s)
            TEMP_FILE="./data/webui_temp_${TIMESTAMP}.db"
            if ! cp "./data/webui.db" "$TEMP_FILE"; then
                echo "复制数据库文件失败,跳过本次同步"
                continue
            fi

            # 生成当前时间的文件名
            FILENAME="webui_$(date +'%m_%d_%H%M').db"
            echo "同步到 WebDAV: $FILENAME"

            # 使用带验证的上传函数上传文件
            if upload_with_verification "$TEMP_FILE" "$WEBDAV_URL/$FILENAME"; then
                echo "文件 $FILENAME 上传成功"
                
                # 更新主文件 webui.db
                if upload_with_verification "$TEMP_FILE" "$WEBDAV_URL/webui.db"; then
                    echo "主文件 webui.db 更新成功"
                else
                    echo "主文件 webui.db 更新失败"
                fi
            else
                echo "文件 $FILENAME 上传失败"
            fi

            # 删除临时副本
            rm -f "$TEMP_FILE"

            # 清理远程旧文件
            clean_remote_files

            # 清理本地旧文件(保留最新3个)
            echo "清理本地旧备份..."
            find "./data" -name "webui_*.db" -type f -printf "%T@ %p\n" | \
                sort -rn | tail -n +4 | cut -d' ' -f2- | xargs rm -f
            echo "本地备份清理完成"
        else
            echo "未找到 webui.db 文件,跳过同步"
        fi

        echo "当前时间 $(date '+%Y-%m-%d %H:%M:%S')"
        echo "等待 ${SYNC_INTERVAL} 秒后进行下一次同步..."
        sleep $SYNC_INTERVAL
    done
}

# 后台启动同步进程
sync_data &