- 文件上传验证: ModelUploader组件增强、上传API错误处理 - GLTF解析器: 增强节点提取和元数据 - 板材编辑: PanelEditor客户端验证 + panels API服务端验证 - 装配步骤编辑: 修复未使用代码,添加预览按钮 - 装配动画播放: AssemblyPlayer步骤导航边界检查优化 - 分享链接: 完整CRUD API(创建、获取、删除),含验证和过期检查 跳过可选测试任务以加快MVP开发
168 lines
5.5 KiB
PowerShell
168 lines
5.5 KiB
PowerShell
# ============================================
|
||
# 系统恢复脚本 (PowerShell)
|
||
# ============================================
|
||
# 功能:
|
||
# - 从指定的完整备份目录恢复数据库和文件存储
|
||
# - 恢复前先执行一次完整备份作为 "before-restore" 快照
|
||
# 使用:
|
||
# .\scripts\restore.ps1 -BackupDir ".\backups\full\20251218-120000"
|
||
# ============================================
|
||
|
||
param(
|
||
[Parameter(Mandatory = $true)]
|
||
[string]$BackupDir
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
|
||
$databaseDir = Join-Path $BackupDir "database"
|
||
$filesDir = Join-Path $BackupDir "files"
|
||
|
||
if (-not (Test-Path $databaseDir) -or -not (Test-Path $filesDir)) {
|
||
Write-Host "错误:$BackupDir 下未找到 database/ 或 files/ 子目录。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host "========================================"
|
||
Write-Host " 系统恢复脚本"
|
||
Write-Host "========================================"
|
||
Write-Host "目标备份目录: $BackupDir"
|
||
Write-Host "警告:该操作会覆盖当前数据库和文件存储,请确保在测试环境中执行。" -ForegroundColor Yellow
|
||
Write-Host "========================================"
|
||
|
||
$confirm = Read-Host "确认继续恢复?(yes/[no])"
|
||
if ($confirm -ne "yes") {
|
||
Write-Host "已取消恢复操作。"
|
||
exit 0
|
||
}
|
||
|
||
# 0. 恢复前先做一次完整备份
|
||
Write-Host "`n[步骤 0] 恢复前备份当前系统..."
|
||
& .\scripts\backup-all.ps1 -BackupRoot ".\backups\before-restore" || `
|
||
Write-Host "恢复前备份失败(已记录),继续尝试恢复..." -ForegroundColor Yellow
|
||
|
||
# 1. 恢复数据库
|
||
Write-Host "`n[步骤 1] 恢复数据库..."
|
||
|
||
# 加载当前 .env 中的 DATABASE_URL
|
||
if (Test-Path ".env") {
|
||
Get-Content .env | ForEach-Object {
|
||
if ($_ -match '^([^#][^=]+)=(.*)$') {
|
||
$name = $matches[1].Trim()
|
||
$value = $matches[2].Trim()
|
||
[Environment]::SetEnvironmentVariable($name, $value, "Process")
|
||
}
|
||
}
|
||
}
|
||
|
||
$databaseUrl = $env:DATABASE_URL
|
||
if (-not $databaseUrl) {
|
||
Write-Host "错误:未在当前环境或 .env 中找到 DATABASE_URL,无法恢复数据库。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
$dbBackup = Get-ChildItem -Path $databaseDir -Filter "db-backup-*.sql.gz" -ErrorAction SilentlyContinue |
|
||
Sort-Object LastWriteTime -Descending |
|
||
Select-Object -First 1
|
||
|
||
if (-not $dbBackup) {
|
||
Write-Host "错误:在 $databaseDir 下未找到 db-backup-*.sql.gz 文件。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host "使用备份文件: $($dbBackup.FullName)"
|
||
|
||
# 解压到临时文件再用 psql 恢复
|
||
$tempSql = Join-Path $databaseDir "restore-temp.sql"
|
||
|
||
# 选择压缩工具
|
||
$compressTool = $null
|
||
if (Get-Command 7z -ErrorAction SilentlyContinue) {
|
||
$compressTool = "7z"
|
||
} elseif (Get-Command gzip -ErrorAction SilentlyContinue) {
|
||
$compressTool = "gzip"
|
||
}
|
||
|
||
if (-not $compressTool) {
|
||
Write-Host "错误:未找到解压工具(7z 或 gzip),无法恢复数据库。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
if ($compressTool -eq "7z") {
|
||
& 7z x -so $dbBackup.FullName | Out-File -FilePath $tempSql -Encoding ASCII
|
||
} else {
|
||
& gzip -cd $dbBackup.FullName > $tempSql
|
||
}
|
||
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Host "错误:解压数据库备份失败。" -ForegroundColor Red
|
||
if (Test-Path $tempSql) { Remove-Item $tempSql -Force }
|
||
exit 1
|
||
}
|
||
|
||
# 使用 psql 和连接字符串恢复
|
||
& psql $databaseUrl -f $tempSql
|
||
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Host "错误:数据库恢复失败。" -ForegroundColor Red
|
||
if (Test-Path $tempSql) { Remove-Item $tempSql -Force }
|
||
exit 1
|
||
}
|
||
|
||
if (Test-Path $tempSql) { Remove-Item $tempSql -Force }
|
||
|
||
Write-Host "数据库恢复完成。" -ForegroundColor Green
|
||
|
||
# 2. 恢复文件存储 (MinIO)
|
||
Write-Host "`n[步骤 2] 恢复文件存储 (MinIO)..."
|
||
|
||
$filesBackup = Get-ChildItem -Path $filesDir -Filter "files-backup-*.tar.gz" -ErrorAction SilentlyContinue |
|
||
Sort-Object LastWriteTime -Descending |
|
||
Select-Object -First 1
|
||
|
||
if (-not $filesBackup) {
|
||
Write-Host "错误:在 $filesDir 下未找到 files-backup-*.tar.gz 文件。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host "使用备份文件: $($filesBackup.FullName)"
|
||
|
||
$minioDataDir = $env:MINIO_DATA_DIR
|
||
if (-not $minioDataDir) {
|
||
$minioDataDir = ".\minio-data"
|
||
}
|
||
|
||
if (-not (Test-Path $minioDataDir)) {
|
||
New-Item -ItemType Directory -Path $minioDataDir -Force | Out-Null
|
||
}
|
||
|
||
Write-Host "清空当前 MinIO 数据目录: $minioDataDir" -ForegroundColor Yellow
|
||
Get-ChildItem -Path $minioDataDir -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force
|
||
|
||
# 解压 tar.gz 到父目录
|
||
$parentDir = Split-Path $minioDataDir -Parent
|
||
|
||
# 选择解压命令
|
||
if (Get-Command tar -ErrorAction SilentlyContinue) {
|
||
& tar -xzf $filesBackup.FullName -C $parentDir
|
||
} elseif (Get-Command 7z -ErrorAction SilentlyContinue) {
|
||
& 7z x $filesBackup.FullName -o$parentDir -y | Out-Null
|
||
} else {
|
||
Write-Host "错误:未找到解压工具(tar 或 7z),无法恢复文件存储。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Host "错误:文件存储恢复失败。" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host "文件存储恢复完成。" -ForegroundColor Green
|
||
|
||
Write-Host "`n========================================"
|
||
Write-Host " 🎉 系统恢复完成 (基础版本)" -ForegroundColor Green
|
||
Write-Host "========================================"
|
||
Write-Host "来源备份: $BackupDir"
|
||
Write-Host "恢复前快照目录: .\backups\before-restore"
|
||
Write-Host "========================================"
|