#!/bin/bash # 云端数据库一键备份脚本 # 用法:bash backup-db.sh set -e TIMESTAMP=$(date +%Y%m%d_%H%M%S) LOCAL_DIR="/Users/niuniu/programs/docker/db-backups" log() { echo "[$(date '+%H:%M:%S')] $1"; } log "开始备份云端数据库..." # 备份前执行 WAL checkpoint,确保数据全部合并到 .db 主文件 log "执行 WAL checkpoint (assets)..." ssh txjp "docker exec assets-ai node -e \"const D=require('better-sqlite3');const db=new D('/app/data/assets.db');db.pragma('wal_checkpoint(TRUNCATE)');db.close();\"" log "执行 WAL checkpoint (issue)..." ssh txjp "docker exec issue-ai node -e \"const D=require('better-sqlite3');const db=new D('/app/data/issue.db');db.pragma('wal_checkpoint(TRUNCATE)');db.close();\"" # 云端打包 ssh txjp "mkdir -p /tmp/db-backup && \ cp /root/docker/assets-ai/data/assets.db /tmp/db-backup/assets-${TIMESTAMP}.db && \ cp /root/docker/issue-ai/data/issue.db /tmp/db-backup/issue-${TIMESTAMP}.db" # 确保本地备份目录存在 mkdir -p "${LOCAL_DIR}" # 云端留一份持久备份 CLOUD_DIR="/root/docker/db-backups" ssh txjp "mkdir -p ${CLOUD_DIR} && \ cp /tmp/db-backup/assets-${TIMESTAMP}.db ${CLOUD_DIR}/assets-${TIMESTAMP}.db && \ cp /tmp/db-backup/issue-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db" log "云端备份已保存至: ${CLOUD_DIR}" # 复制到本地 log "复制到本地..." mkdir -p "${LOCAL_DIR}" scp "txjp:/tmp/db-backup/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/" scp "txjp:/tmp/db-backup/issue-${TIMESTAMP}.db" "${LOCAL_DIR}/" # 验证备份文件为有效 SQLite 数据库 log "验证备份完整性..." for f in "${LOCAL_DIR}/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/issue-${TIMESTAMP}.db"; do if ! sqlite3 "$f" "SELECT count(*) FROM sqlite_master" > /dev/null 2>&1; then echo "[错误] 备份文件无效或损坏: $f" exit 1 fi done log "备份文件验证通过" # 清理云端临时文件 ssh txjp "rm -rf /tmp/db-backup" log "备份完成:${TIMESTAMP}" echo " 云端: ${CLOUD_DIR}/" ssh txjp "ls -lh ${CLOUD_DIR}/assets-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db 2>/dev/null" echo " 本地:" ls -lh "${LOCAL_DIR}"/assets-${TIMESTAMP}.db "${LOCAL_DIR}"/issue-${TIMESTAMP}.db 2>/dev/null