| #!/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})..." |
|
|
| FULL_WEBDAV_URL="${WEBDAV_URL}/${REMOTE_BACKUP_DIR}" |
| local_path="${BACKUP_PATH}/${BACKUP_FILENAME}" |
| remote_file="${BACKUP_FILENAME}" |
|
|
| if [ -f "$local_path" ]; then |
| curl -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "$local_path" "$FULL_WEBDAV_URL/$remote_file" |
| 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 |
| else |
| log "错误: 本地备份文件不存在" |
| 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 |