simple-v / sync_db.sh
hzruo's picture
Create sync_db.sh
2b8ef3a verified
#!/bin/bash
# 设置颜色
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# 日志函数
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
}
log "数据库同步脚本启动"
# 检查环境变量
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
echo -e "${YELLOW}WebDAV 配置不完整,跳过同步${NC}"
exit 0
fi
# 同步间隔(秒)
INTERVAL=${SYNC_INTERVAL:-600}
log "同步间隔设置为 $INTERVAL 秒"
# 数据库路径
DB_PATH=${DB_PATH:-/app/data/video-player.db}
log "数据库路径: $DB_PATH"
# 确保数据目录存在
mkdir -p $(dirname $DB_PATH)
# 使用 TMPDIR 环境变量
TEMP_DIR=${TMPDIR:-"/tmp"}
DB_DOWNLOAD_PATH="${TEMP_DIR}/video-player.db.download"
BACKUP_DIR="${TEMP_DIR}/backup"
# 设置备份路径
WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-"video-player-data"}
FULL_WEBDAV_URL="${WEBDAV_URL}"
# 确保 WEBDAV_URL 以斜杠结尾
if [ "${WEBDAV_URL: -1}" != "/" ]; then
WEBDAV_URL="${WEBDAV_URL}/"
fi
if [ -n "$WEBDAV_BACKUP_PATH" ]; then
FULL_WEBDAV_URL="${WEBDAV_URL}${WEBDAV_BACKUP_PATH}"
# 确保 FULL_WEBDAV_URL 以斜杠结尾
if [ "${FULL_WEBDAV_URL: -1}" != "/" ]; then
FULL_WEBDAV_URL="${FULL_WEBDAV_URL}/"
fi
fi
log "WebDAV 同步已配置:"
log " URL: ${FULL_WEBDAV_URL}"
log " 同步间隔: ${INTERVAL}秒"
# 检查 WebDAV 连接和权限
check_webdav_connection() {
log "检查 WebDAV 连接和权限..."
# 尝试列出根目录
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X PROPFIND -H "Depth: 1" "${FULL_WEBDAV_URL}/")
if [ "$HTTP_CODE" = "207" ] || [ "$HTTP_CODE" = "200" ]; then
log "WebDAV 连接成功"
return 0
elif [ "$HTTP_CODE" = "404" ]; then
echo -e "${YELLOW}WebDAV 路径不存在,尝试创建...${NC}"
# 尝试创建主目录
create_main_dir
return $?
elif [ "$HTTP_CODE" = "401" ]; then
echo -e "${RED}WebDAV 认证失败,请检查用户名和密码${NC}"
return 1
elif [ "$HTTP_CODE" = "403" ]; then
echo -e "${RED}WebDAV 权限不足,无法访问${NC}"
return 1
else
echo -e "${RED}WebDAV 连接失败: HTTP 状态码 ${HTTP_CODE}${NC}"
return 1
fi
}
# 创建主目录
create_main_dir() {
# 如果路径包含多级目录,需要逐级创建
IFS='/' read -ra DIRS <<< "$WEBDAV_BACKUP_PATH"
CURRENT_PATH=""
for DIR in "${DIRS[@]}"; do
if [ -z "$DIR" ]; then
continue
fi
if [ -z "$CURRENT_PATH" ]; then
CURRENT_PATH="$DIR"
else
CURRENT_PATH="$CURRENT_PATH/$DIR"
fi
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X MKCOL "${WEBDAV_URL}${CURRENT_PATH}/")
if [ "$HTTP_CODE" = "201" ]; then
log "创建目录成功: ${CURRENT_PATH}"
elif [ "$HTTP_CODE" = "405" ]; then
echo -e "${YELLOW}目录已存在: ${CURRENT_PATH}${NC}"
elif [ "$HTTP_CODE" = "409" ]; then
echo -e "${YELLOW}父目录不存在: ${CURRENT_PATH}${NC}"
return 1
elif [ "$HTTP_CODE" = "403" ]; then
echo -e "${RED}无权限创建目录: ${CURRENT_PATH}${NC}"
return 1
else
echo -e "${RED}创建目录失败: ${CURRENT_PATH}, HTTP 状态码 ${HTTP_CODE}${NC}"
return 1
fi
done
# 创建备份子目录
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X MKCOL "${FULL_WEBDAV_URL}backups/")
if [ "$HTTP_CODE" = "201" ]; then
log "创建备份目录成功"
return 0
elif [ "$HTTP_CODE" = "405" ]; then
echo -e "${YELLOW}备份目录已存在${NC}"
return 0
elif [ "$HTTP_CODE" = "403" ]; then
echo -e "${RED}无权限创建备份目录${NC}"
return 1
else
echo -e "${RED}创建备份目录失败: HTTP 状态码 ${HTTP_CODE}${NC}"
return 1
fi
}
# 从 WebDAV 下载数据库
download_db() {
log "从 WebDAV 下载数据库..."
# 使用 curl 下载数据库文件
HTTP_CODE=$(curl -s -o "${DB_DOWNLOAD_PATH}" -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "${FULL_WEBDAV_URL}video-player.db")
if [ "$HTTP_CODE" = "200" ]; then
# 检查文件是否为有效的 SQLite 数据库
if [ -s "${DB_DOWNLOAD_PATH}" ]; then
log "成功下载数据库文件"
# 如果当前没有数据库或下载的数据库更新,则使用下载的数据库
if [ ! -f "$DB_PATH" ] || [ $(stat -c %Y "${DB_DOWNLOAD_PATH}" 2>/dev/null || echo 0) -gt $(stat -c %Y "$DB_PATH" 2>/dev/null || echo 0) ]; then
cp "${DB_DOWNLOAD_PATH}" "$DB_PATH"
log "已更新本地数据库"
else
echo -e "${YELLOW}本地数据库已是最新版本${NC}"
rm "${DB_DOWNLOAD_PATH}"
fi
else
echo -e "${RED}下载的文件不是有效的文件${NC}"
rm "${DB_DOWNLOAD_PATH}"
fi
elif [ "$HTTP_CODE" = "404" ]; then
echo -e "${YELLOW}WebDAV 上不存在数据库文件,将使用本地数据库${NC}"
rm -f "${DB_DOWNLOAD_PATH}"
else
echo -e "${RED}下载数据库失败: HTTP 状态码 ${HTTP_CODE}${NC}"
rm -f "${DB_DOWNLOAD_PATH}"
fi
}
# 上传数据库到 WebDAV
upload_db() {
log "上传数据库到 WebDAV..."
# 确保数据库文件存在
if [ ! -f "$DB_PATH" ]; then
echo -e "${YELLOW}本地数据库文件不存在,跳过上传${NC}"
return
fi
# 确保备份目录存在
log "确保备份目录存在..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X PROPFIND -H "Depth: 1" "${FULL_WEBDAV_URL}backups/")
if [ "$HTTP_CODE" != "207" ] && [ "$HTTP_CODE" != "200" ]; then
log "备份目录不存在,尝试创建..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X MKCOL "${FULL_WEBDAV_URL}backups/")
if [ "$HTTP_CODE" != "201" ] && [ "$HTTP_CODE" != "405" ]; then
echo -e "${RED}创建备份目录失败: HTTP 状态码 ${HTTP_CODE}${NC}"
echo -e "${YELLOW}将跳过备份上传,但会继续上传主数据库文件${NC}"
else
log "备份目录创建成功"
fi
else
log "备份目录已存在"
fi
# 创建备份目录(如果不存在)
mkdir -p "${BACKUP_DIR}"
# 创建带时间戳的备份
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
cp "$DB_PATH" "${BACKUP_DIR}/video-player_${TIMESTAMP}.db"
# 上传当前数据库
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "$DB_PATH" "${FULL_WEBDAV_URL}video-player.db")
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "204" ]; then
log "成功上传数据库"
# 尝试上传到备份目录
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "${BACKUP_DIR}/video-player_${TIMESTAMP}.db" "${FULL_WEBDAV_URL}backups/video-player_${TIMESTAMP}.db")
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "204" ]; then
log "成功上传数据库备份 video-player_${TIMESTAMP}.db"
elif [ "$HTTP_CODE" = "403" ] || [ "$HTTP_CODE" = "405" ]; then
log "备份目录上传失败,尝试直接上传到主目录..."
# 尝试直接上传到主目录
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "${BACKUP_DIR}/video-player_${TIMESTAMP}.db" "${FULL_WEBDAV_URL}video-player_backup_${TIMESTAMP}.db")
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "204" ]; then
log "成功上传数据库备份到主目录 video-player_backup_${TIMESTAMP}.db"
else
echo -e "${YELLOW}上传数据库备份到主目录也失败: HTTP 状态码 ${HTTP_CODE}${NC}"
echo -e "${YELLOW}备份文件路径: ${BACKUP_DIR}/video-player_${TIMESTAMP}.db${NC}"
echo -e "${YELLOW}目标 URL: ${FULL_WEBDAV_URL}video-player_backup_${TIMESTAMP}.db${NC}"
fi
else
echo -e "${YELLOW}上传数据库备份失败: HTTP 状态码 ${HTTP_CODE}${NC}"
echo -e "${YELLOW}备份文件路径: ${BACKUP_DIR}/video-player_${TIMESTAMP}.db${NC}"
echo -e "${YELLOW}目标 URL: ${FULL_WEBDAV_URL}backups/video-player_${TIMESTAMP}.db${NC}"
fi
else
echo -e "${RED}上传数据库失败: HTTP 状态码 ${HTTP_CODE}${NC}"
fi
# 清理临时文件
rm -rf "${BACKUP_DIR}"
}
# 清理旧备份
cleanup_old_backups() {
log "清理旧备份..."
# 首先尝试列出备份目录中的备份
# 使用 curl 列出目录内容
BACKUPS=$(curl -s -X PROPFIND -H "Depth: 1" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "${FULL_WEBDAV_URL}backups/" | grep -o "backups/video-player_[0-9]\{8\}_[0-9]\{6\}.db" | sort)
# 如果备份目录中没有备份,尝试列出主目录中的备份
if [ -z "$BACKUPS" ]; then
log "备份目录中没有找到备份,尝试在主目录中查找..."
BACKUPS=$(curl -s -X PROPFIND -H "Depth: 1" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" "${FULL_WEBDAV_URL}" | grep -o "video-player_backup_[0-9]\{8\}_[0-9]\{6\}.db" | sort)
fi
# 计算要删除的备份数量(保留最新的5个)
KEEP_COUNT=${BACKUP_KEEP_COUNT:-5}
BACKUP_COUNT=$(echo "$BACKUPS" | wc -l)
DELETE_COUNT=$((BACKUP_COUNT - KEEP_COUNT))
if [ $DELETE_COUNT -gt 0 ]; then
log "找到 ${BACKUP_COUNT} 个备份,将删除最旧的 ${DELETE_COUNT} 个"
# 获取要删除的备份列表
TO_DELETE=$(echo "$BACKUPS" | head -n $DELETE_COUNT)
# 删除旧备份
for BACKUP in $TO_DELETE; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -X DELETE "${FULL_WEBDAV_URL}${BACKUP}")
if [ "$HTTP_CODE" = "204" ] || [ "$HTTP_CODE" = "200" ]; then
log "已删除旧备份: ${BACKUP}"
else
echo -e "${YELLOW}删除旧备份失败: ${BACKUP}, HTTP 状态码 ${HTTP_CODE}${NC}"
fi
done
else
log "备份数量不超过5个,无需清理"
fi
}
# 首次启动时检查 WebDAV 连接并下载数据库
if check_webdav_connection; then
download_db
else
echo -e "${YELLOW}WebDAV 连接或权限问题,将使用本地数据库${NC}"
fi
# 主循环
while true; do
log "开始同步过程: $(date)"
# 检查 WebDAV 连接
if check_webdav_connection; then
# 上传数据库
upload_db
# 清理旧备份
cleanup_old_backups
else
echo -e "${RED}WebDAV 连接或权限问题,跳过本次同步${NC}"
fi
log "同步完成,下次同步将在 ${INTERVAL} 秒后进行..."
sleep $INTERVAL
done