webx / sync_data.sh
zx2323's picture
Update sync_data.sh
8d932ae verified
#!/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 &