File size: 7,014 Bytes
c1ccdca e1ffe54 c1ccdca e1ffe54 c1ccdca e1ffe54 c1ccdca e1ffe54 c1ccdca e1ffe54 c1ccdca e1ffe54 c1ccdca e1ffe54 c1ccdca |
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 |
#!/bin/bash
set -e
WEBDAV_URL="${WEBDAV_URL}"
WEBDAV_USERNAME="${WEBDAV_USERNAME}"
WEBDAV_PASSWORD="${WEBDAV_PASSWORD}"
DB_PATH="${DB_PATH:-/app/db}"
BACKUP_PATH="${BACKUP_PATH:-/app/backup}"
BACKUP_FILENAME="${BACKUP_FILENAME:-tgdrive_db_backup.tar.gz}"
REMOTE_BACKUP_DIR="${REMOTE_BACKUP_DIR:-tgdrive_backup}"
CONFIG_FILE="/app/config/sync_config"
PYTHON_CMD="/app/venv/bin/python3"
mkdir -p ${BACKUP_PATH}
mkdir -p /app/logs
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> /app/logs/sync.log 2>/dev/null || true
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
}
mkdir -p /app/logs 2>/dev/null || true
touch /app/logs/sync.log 2>/dev/null || true
if [ ! -f "$CONFIG_FILE" ]; then
log "创建初始配置文件"
mkdir -p /app/config 2>/dev/null || true
echo "LAST_SYNC=0" > "$CONFIG_FILE" 2>/dev/null || true
fi
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE" 2>/dev/null || true
fi
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
log "错误: WebDAV配置不完整,请设置WEBDAV_URL, WEBDAV_USERNAME, WEBDAV_PASSWORD环境变量"
exit 1
fi
backup_db() {
log "开始备份数据库..."
if [ -d "$DB_PATH" ]; then
if [[ "$DB_PATH" == "/app/db" ]]; then
tar -czf "${BACKUP_PATH}/${BACKUP_FILENAME}" -C /app db
else
tar -czf "${BACKUP_PATH}/${BACKUP_FILENAME}" -C $(dirname "$DB_PATH") $(basename "$DB_PATH")
fi
log "数据库已备份到 ${BACKUP_PATH}/${BACKUP_FILENAME}"
return 0
else
log "警告: 数据库目录不存在"
return 1
fi
}
upload_to_webdav() {
log "开始上传备份到WebDAV (目标目录: ${REMOTE_BACKUP_DIR})..."
$PYTHON_CMD -c "
import webdav3.client as wc
import os
options = {
'webdav_hostname': '$WEBDAV_URL',
'webdav_login': '$WEBDAV_USERNAME',
'webdav_password': '$WEBDAV_PASSWORD',
'webdav_timeout': 30
}
client = wc.Client(options)
# 检查远程目录是否存在
if not client.check('$REMOTE_BACKUP_DIR'):
client.mkdir('$REMOTE_BACKUP_DIR')
# 上传文件
local_path = '${BACKUP_PATH}/${BACKUP_FILENAME}'
remote_path = '$REMOTE_BACKUP_DIR/${BACKUP_FILENAME}'
if os.path.exists(local_path):
try:
client.upload_sync(remote_path=remote_path, local_path=local_path)
print('上传成功')
except Exception as e:
print(f'上传失败: {e}')
else:
print('本地备份文件不存在')
"
if [ $? -eq 0 ]; then
log "备份已成功上传到WebDAV (${REMOTE_BACKUP_DIR}/${BACKUP_FILENAME})"
echo "LAST_SYNC=$(date +%s)" > "$CONFIG_FILE"
return 0
else
log "上传到WebDAV失败"
return 1
fi
}
download_from_webdav() {
log "开始从WebDAV下载备份 (源目录: ${REMOTE_BACKUP_DIR})..."
$PYTHON_CMD -c "
import webdav3.client as wc
import os
options = {
'webdav_hostname': '$WEBDAV_URL',
'webdav_login': '$WEBDAV_USERNAME',
'webdav_password': '$WEBDAV_PASSWORD',
'webdav_timeout': 30
}
client = wc.Client(options)
# 检查远程文件是否存在
remote_path = '$REMOTE_BACKUP_DIR/${BACKUP_FILENAME}'
local_path = '${BACKUP_PATH}/${BACKUP_FILENAME}'
if client.check(remote_path):
try:
client.download_sync(remote_path=remote_path, local_path=local_path)
print('下载成功')
except Exception as e:
print(f'下载失败: {e}')
else:
print('远程备份文件不存在')
"
if [ $? -eq 0 ]; then
log "备份已成功从WebDAV (${REMOTE_BACKUP_DIR}/${BACKUP_FILENAME}) 下载"
return 0
else
log "从WebDAV下载备份失败"
return 1
fi
}
restore_db() {
log "开始恢复数据库到 ${DB_PATH}..."
if [ -f "${BACKUP_PATH}/${BACKUP_FILENAME}" ]; then
if [ -d "$DB_PATH" ] && [ "$(ls -A $DB_PATH 2>/dev/null)" ]; then
local timestamp=$(date +%Y%m%d%H%M%S)
if [[ "$DB_PATH" == "/app/db" ]]; then
tar -czf "${BACKUP_PATH}/db_before_restore_${timestamp}.tar.gz" -C /app db 2>/dev/null || log "无法创建当前数据库备份,继续恢复..."
else
tar -czf "${BACKUP_PATH}/db_before_restore_${timestamp}.tar.gz" -C $(dirname "$DB_PATH") $(basename "$DB_PATH") 2>/dev/null || log "无法创建当前数据库备份,继续恢复..."
fi
log "尝试备份当前数据库到 ${BACKUP_PATH}/db_before_restore_${timestamp}.tar.gz"
fi
# 创建临时恢复目录
mkdir -p /tmp/tgdrive_restore 2>/dev/null || true
# 解压备份文件到临时目录
tar -xzf "${BACKUP_PATH}/${BACKUP_FILENAME}" -C /tmp/tgdrive_restore 2>/dev/null || {
log "解压备份文件失败,可能是格式不正确"
rm -rf /tmp/tgdrive_restore 2>/dev/null || true
return 1
}
# 确保数据库目录存在
mkdir -p "$DB_PATH" 2>/dev/null || true
# 清空数据库目录内容(逐个文件删除而不是删除整个目录)
find "$DB_PATH" -mindepth 1 -delete 2>/dev/null || log "无法清空数据库目录,将尝试直接覆盖..."
# 复制恢复的文件到数据库目录
if [ -d "/tmp/tgdrive_restore/db" ]; then
cp -rf /tmp/tgdrive_restore/db/* "$DB_PATH"/ 2>/dev/null || {
log "复制恢复文件失败,尝试使用rsync..."
which rsync >/dev/null 2>&1 && rsync -a /tmp/tgdrive_restore/db/ "$DB_PATH"/ 2>/dev/null
}
else
log "备份中找不到db目录,尝试直接复制临时目录内容..."
cp -rf /tmp/tgdrive_restore/* "$DB_PATH"/ 2>/dev/null || {
log "复制恢复文件失败,尝试使用rsync..."
which rsync >/dev/null 2>&1 && rsync -a /tmp/tgdrive_restore/ "$DB_PATH"/ 2>/dev/null
}
fi
rm -rf /tmp/tgdrive_restore 2>/dev/null || true
log "数据库已尝试恢复到 ${DB_PATH}"
return 0
else
log "错误: 备份文件不存在,无法恢复数据库"
return 1
fi
}
case "$1" in
backup)
backup_db && upload_to_webdav
;;
restore)
download_from_webdav && restore_db
;;
sync)
current_time=$(date +%s)
download_from_webdav
if { [ ! -d "$DB_PATH" ] || [ ! "$(ls -A $DB_PATH 2>/dev/null)" ]; } && [ -f "${BACKUP_PATH}/${BACKUP_FILENAME}" ]; then
log "检测到本地数据库不存在或为空,开始恢复..."
restore_db
fi
backup_db && upload_to_webdav
;;
*)
echo "用法: $0 {backup|restore|sync}"
echo " backup - 备份数据库并上传到WebDAV"
echo " restore - 从WebDAV下载备份并恢复数据库"
echo " sync - 同步数据库(双向)"
exit 1
;;
esac
exit 0 |