239 lines
7.4 KiB
PowerShell
239 lines
7.4 KiB
PowerShell
# 使用 SSH 密钥的部署脚本(更安全)
|
||
param(
|
||
[string]$Server = "45.249.208.118",
|
||
[string]$User = "root",
|
||
[string]$SshKeyPath = "$env:USERPROFILE\.ssh\id_rsa", # 默认 SSH 密钥路径
|
||
[string]$ProjectPath = "/root/youyidian-3d",
|
||
[switch]$NoCache = $false
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
|
||
Write-Host "========================================" -ForegroundColor Cyan
|
||
Write-Host " 安全部署脚本 - 使用 SSH 密钥" -ForegroundColor Cyan
|
||
Write-Host "========================================" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
|
||
# 检查工具
|
||
$plinkPath = "C:\Program Files\PuTTY\plink.exe"
|
||
$pscpPath = "C:\Program Files\PuTTY\pscp.exe"
|
||
|
||
if (-not (Test-Path $plinkPath)) {
|
||
Write-Host "错误: 未找到 plink.exe,请安装 PuTTY" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
# 检查 SSH 密钥文件
|
||
if (-not (Test-Path $SshKeyPath)) {
|
||
Write-Host "错误: 未找到 SSH 密钥文件: $SshKeyPath" -ForegroundColor Red
|
||
Write-Host ""
|
||
Write-Host "请执行以下步骤创建 SSH 密钥:" -ForegroundColor Yellow
|
||
Write-Host " 1. 生成密钥对: ssh-keygen -t rsa -b 4096 -C `"deploy@youyidian`"" -ForegroundColor Gray
|
||
Write-Host " 2. 将公钥复制到服务器: ssh-copy-id -i ~/.ssh/id_rsa.pub ${User}@${Server}" -ForegroundColor Gray
|
||
Write-Host " 3. 或者手动复制公钥内容到服务器的 ~/.ssh/authorized_keys" -ForegroundColor Gray
|
||
Write-Host ""
|
||
Write-Host "如果你使用 PuTTY,可以:" -ForegroundColor Yellow
|
||
Write-Host " 1. 使用 PuTTYgen 生成密钥对" -ForegroundColor Gray
|
||
Write-Host " 2. 将公钥添加到服务器的 ~/.ssh/authorized_keys" -ForegroundColor Gray
|
||
Write-Host " 3. 在 Pageant 中加载私钥,或使用 -i 参数指定私钥文件" -ForegroundColor Gray
|
||
exit 1
|
||
}
|
||
|
||
Write-Host "使用 SSH 密钥: $SshKeyPath" -ForegroundColor Green
|
||
Write-Host ""
|
||
|
||
# 需要上传的关键文件
|
||
$filesToUpload = @(
|
||
"app/page.tsx",
|
||
"app/login/page.tsx",
|
||
"app/api/network-status/route.ts",
|
||
"next.config.js",
|
||
"README.md",
|
||
"lib/config.ts",
|
||
"lib/configLoader.ts",
|
||
"config-bianliang.env",
|
||
"Dockerfile",
|
||
"docker-compose.yml",
|
||
"package.json",
|
||
"package-lock.json"
|
||
)
|
||
|
||
# 检查文件是否存在
|
||
$missingFiles = @()
|
||
foreach ($file in $filesToUpload) {
|
||
if (-not (Test-Path $file)) {
|
||
$missingFiles += $file
|
||
}
|
||
}
|
||
|
||
if ($missingFiles.Count -gt 0) {
|
||
Write-Host "警告: 以下文件不存在,将跳过:" -ForegroundColor Yellow
|
||
$missingFiles | ForEach-Object { Write-Host " - $_" -ForegroundColor Yellow }
|
||
}
|
||
|
||
# 上传文件
|
||
Write-Host "[1/5] 上传文件到服务器..." -ForegroundColor Yellow
|
||
|
||
$uploadedCount = 0
|
||
foreach ($file in $filesToUpload) {
|
||
if (Test-Path $file) {
|
||
$remotePath = "$ProjectPath/$file"
|
||
$remoteDir = Split-Path $remotePath -Parent
|
||
|
||
# 确保远程目录存在
|
||
& $plinkPath -ssh -i $SshKeyPath -batch "${User}@${Server}" "mkdir -p `"$remoteDir`"" | Out-Null
|
||
|
||
# 上传文件
|
||
& $pscpPath -i $SshKeyPath -batch -q $file "${User}@${Server}:$remotePath" 2>&1 | Out-Null
|
||
|
||
if ($LASTEXITCODE -eq 0) {
|
||
$uploadedCount++
|
||
Write-Host " ✓ $file" -ForegroundColor Green
|
||
} else {
|
||
Write-Host " ✗ $file (上传失败)" -ForegroundColor Red
|
||
}
|
||
}
|
||
}
|
||
|
||
Write-Host "已上传 $uploadedCount/$($filesToUpload.Count) 个文件" -ForegroundColor $(if ($uploadedCount -eq $filesToUpload.Count) { "Green" } else { "Yellow" })
|
||
|
||
# 创建部署脚本
|
||
Write-Host "[2/5] 创建部署脚本..." -ForegroundColor Yellow
|
||
|
||
$buildFlag = if ($NoCache) { "--no-cache" } else { "" }
|
||
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
||
$deployScript = @"
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
cd $ProjectPath
|
||
|
||
echo "========================================"
|
||
echo "开始部署..."
|
||
echo "========================================"
|
||
|
||
# 备份数据
|
||
echo "[1/6] 备份数据..."
|
||
if [ -d "uploads" ]; then
|
||
mkdir -p backups
|
||
backup_dir="backups/uploads-$(date +%Y%m%d-%H%M%S)"
|
||
cp -r uploads "`$backup_dir" 2>/dev/null || true
|
||
echo " ✓ 上传目录已备份到 `$backup_dir"
|
||
fi
|
||
|
||
# 检查环境
|
||
echo "[2/6] 检查环境..."
|
||
if ! command -v docker &> /dev/null; then
|
||
echo "错误: Docker 未安装" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if docker compose version &> /dev/null; then
|
||
DOCKER_COMPOSE="docker compose"
|
||
elif docker-compose version &> /dev/null; then
|
||
DOCKER_COMPOSE="docker-compose"
|
||
else
|
||
echo "错误: Docker Compose 未安装" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo " ✓ 使用: `$DOCKER_COMPOSE"
|
||
|
||
# 停止旧容器
|
||
echo "[3/6] 停止旧容器..."
|
||
`$DOCKER_COMPOSE down --timeout 30 2>/dev/null || true
|
||
echo " ✓ 旧容器已停止"
|
||
|
||
# 构建并启动
|
||
echo "[4/6] 构建并启动容器..."
|
||
if [ -n "$buildFlag" ]; then
|
||
echo " ⚠ 使用 --no-cache 模式"
|
||
`$DOCKER_COMPOSE build $buildFlag app && `$DOCKER_COMPOSE up -d app
|
||
else
|
||
echo " ✓ 使用智能构建缓存"
|
||
`$DOCKER_COMPOSE up -d --build app
|
||
fi
|
||
|
||
if [ `$? -ne 0 ]; then
|
||
echo "错误: 容器构建或启动失败" >&2
|
||
exit 1
|
||
fi
|
||
echo " ✓ 容器构建并启动完成"
|
||
|
||
# 等待容器就绪
|
||
echo "[5/6] 等待容器就绪..."
|
||
sleep 10
|
||
|
||
max_attempts=30
|
||
attempt=0
|
||
while [ `$attempt -lt `$max_attempts ]; do
|
||
if `$DOCKER_COMPOSE ps app | grep -q "Up"; then
|
||
echo " ✓ 容器运行中"
|
||
break
|
||
fi
|
||
attempt=`$((attempt + 1))
|
||
sleep 2
|
||
done
|
||
|
||
# 数据库迁移
|
||
echo "[6/6] 检查数据库迁移..."
|
||
if [ -f prisma/schema.prisma ]; then
|
||
`$DOCKER_COMPOSE exec -T app npx prisma db push --accept-data-loss --schema=/app/prisma/schema.prisma 2>/dev/null || echo " ⚠ 数据库迁移跳过或已完成"
|
||
fi
|
||
|
||
# 显示结果
|
||
echo ""
|
||
echo "========================================"
|
||
echo "部署完成!"
|
||
echo "========================================"
|
||
echo ""
|
||
echo "容器状态:"
|
||
`$DOCKER_COMPOSE ps
|
||
echo ""
|
||
echo "应用日志(最后 30 行):"
|
||
`$DOCKER_COMPOSE logs app --tail=30
|
||
"@
|
||
|
||
$localDeployScript = Join-Path $env:TEMP "deploy-ssh-$timestamp.sh"
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
||
[System.IO.File]::WriteAllText($localDeployScript, $deployScript, $utf8NoBom)
|
||
|
||
# 上传部署脚本
|
||
Write-Host "[3/5] 上传部署脚本..." -ForegroundColor Yellow
|
||
$remoteDeployScript = "/tmp/deploy-ssh-$timestamp.sh"
|
||
|
||
& $pscpPath -i $SshKeyPath -batch $localDeployScript "${User}@${Server}:$remoteDeployScript"
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Host "上传部署脚本失败" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
Write-Host " ✓ 部署脚本已上传" -ForegroundColor Green
|
||
|
||
# 执行部署
|
||
Write-Host "[4/5] 执行部署..." -ForegroundColor Yellow
|
||
Write-Host ""
|
||
|
||
& $plinkPath -ssh -i $SshKeyPath -batch "${User}@${Server}" "chmod +x $remoteDeployScript; bash $remoteDeployScript; rm -f $remoteDeployScript"
|
||
|
||
$deployExitCode = $LASTEXITCODE
|
||
|
||
# 清理
|
||
Remove-Item $localDeployScript -Force -ErrorAction SilentlyContinue
|
||
|
||
if ($deployExitCode -ne 0) {
|
||
Write-Host ""
|
||
Write-Host "部署失败,退出码: $deployExitCode" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "========================================" -ForegroundColor Green
|
||
Write-Host " 部署成功完成!" -ForegroundColor Green
|
||
Write-Host "========================================" -ForegroundColor Green
|
||
Write-Host ""
|
||
Write-Host "提示:" -ForegroundColor Yellow
|
||
Write-Host " - 使用 -SshKeyPath 参数指定自定义 SSH 密钥路径" -ForegroundColor Gray
|
||
Write-Host " - 使用 -NoCache 参数可以强制重新构建" -ForegroundColor Gray
|
||
Write-Host ""
|
||
|