diff --git a/backup-db.sh b/backup-db.sh index 1e01792..4deea41 100755 --- a/backup-db.sh +++ b/backup-db.sh @@ -29,6 +29,16 @@ log "复制到本地..." 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" diff --git a/restore-db.sh b/restore-db.sh index e3c0e5e..ae8e55b 100755 --- a/restore-db.sh +++ b/restore-db.sh @@ -155,8 +155,10 @@ restore_cloud() { exit 1 fi - # 2. 验证备份文件 - if ! ssh txjp "sqlite3 ${BACKUP_PATH} 'SELECT count(*) FROM sqlite_master' > /dev/null 2>&1"; then + # 2. 验证备份文件(通过临时容器,避免依赖宿主机 sqlite3) + if ! ssh txjp "docker cp ${BACKUP_PATH} ${CONTAINER}:/tmp/restore-check.db 2>/dev/null && \ + docker exec ${CONTAINER} sqlite3 /tmp/restore-check.db 'SELECT count(*) FROM sqlite_master' > /dev/null 2>&1 && \ + docker exec ${CONTAINER} rm /tmp/restore-check.db"; then echo "[错误] 备份文件不是有效的 SQLite 数据库" exit 1 fi @@ -191,21 +193,29 @@ restore_cloud() { exit 0 fi - # 5. 云端安全备份当前数据库 + # 5. 停止容器(确保数据库不被写入,安全替换) + echo "[操作] 停止容器 ${CONTAINER}..." + ssh txjp "cd /root/docker/${PROJECT_DIR} && docker compose stop ${CONTAINER}" + + # 6. 备份当前数据库(容器已停止,安全复制) local SAFE_NAME="before-restore-$(date +%Y%m%d_%H%M%S).db" echo "[操作] 备份云端当前数据库..." ssh txjp "docker cp ${CONTAINER}:${DB_PATH_IN_CONTAINER} /root/docker/db-backups/${SAFE_NAME}" echo "[备份] 当前数据库已保存至云端: /root/docker/db-backups/${SAFE_NAME}" - # 6. 复制备份文件到容器 + # 7. 替换数据库 echo "[操作] 复制备份文件到容器..." ssh txjp "docker cp ${BACKUP_PATH} ${CONTAINER}:${DB_PATH_IN_CONTAINER}" - # 7. 重启容器 - echo "[操作] 重启容器 ${CONTAINER}..." - ssh txjp "cd /root/docker/${PROJECT_DIR} && docker compose restart ${CONTAINER}" + # 8. 删除残留 WAL/SHM 文件,防止旧日志与新数据库不匹配导致损坏 + echo "[操作] 清理残留 WAL/SHM 文件..." + ssh txjp "docker exec ${CONTAINER} rm -f ${DB_PATH_IN_CONTAINER}-shm ${DB_PATH_IN_CONTAINER}-wal" 2>/dev/null || true - # 8. 验证 + # 9. 启动容器 + echo "[操作] 启动容器 ${CONTAINER}..." + ssh txjp "cd /root/docker/${PROJECT_DIR} && docker compose start ${CONTAINER}" + + # 10. 验证 sleep 3 echo "" echo "[验证] 恢复后数据:"