包含: - furniture-3d-system:Next.js 16 全栈应用(资产中心、产品管理、3D装配动画) - autocad-plugin:AutoCAD 家具导出插件源码 - 资产中心改造:编辑弹窗化、删除功能、Toast反馈、自定义Select组件 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
254 lines
9.3 KiB
PowerShell
254 lines
9.3 KiB
PowerShell
# 飞牛OS部署脚本
|
||
# 用途:一键部署到飞牛OS服务器 (192.168.42.252)
|
||
# 使用:.\scripts\deploy-feiniu.ps1
|
||
|
||
param(
|
||
[string]$ServerIP = "192.168.42.252",
|
||
[string]$ServerUser = "admin",
|
||
[string]$ServerPassword = "admin123",
|
||
[string]$RemotePath = "/opt/furniture-3d-system",
|
||
[switch]$SkipUpload = $false,
|
||
[switch]$SkipBuild = $false
|
||
)
|
||
|
||
Write-Host "=== 飞牛OS部署脚本 ===" -ForegroundColor Cyan
|
||
Write-Host "目标服务器: $ServerIP" -ForegroundColor Yellow
|
||
Write-Host "部署路径: $RemotePath`n" -ForegroundColor Yellow
|
||
|
||
# 检查必要的工具
|
||
Write-Host "检查必要工具..." -ForegroundColor Yellow
|
||
|
||
# 检查SSH客户端(Windows 10+自带OpenSSH)
|
||
$sshAvailable = Get-Command ssh -ErrorAction SilentlyContinue
|
||
if (-not $sshAvailable) {
|
||
Write-Host "❌ 未找到SSH客户端" -ForegroundColor Red
|
||
Write-Host "请安装OpenSSH客户端或使用WinSCP等工具手动上传文件" -ForegroundColor Yellow
|
||
exit 1
|
||
}
|
||
Write-Host "✅ SSH客户端可用" -ForegroundColor Green
|
||
|
||
# 检查SCP(用于文件传输)
|
||
$scpAvailable = Get-Command scp -ErrorAction SilentlyContinue
|
||
if (-not $scpAvailable) {
|
||
Write-Host "⚠️ 未找到SCP客户端,将使用SSH命令传输" -ForegroundColor Yellow
|
||
$useScp = $false
|
||
} else {
|
||
Write-Host "✅ SCP客户端可用" -ForegroundColor Green
|
||
$useScp = $true
|
||
}
|
||
|
||
# 检查项目目录
|
||
Write-Host "`n检查项目目录..." -ForegroundColor Yellow
|
||
$projectPath = "d:\3danzhuang\furniture-3d-system"
|
||
if (-not (Test-Path $projectPath)) {
|
||
Write-Host "❌ 项目目录不存在: $projectPath" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
Write-Host "✅ 项目目录存在: $projectPath" -ForegroundColor Green
|
||
|
||
# 检查必要的文件
|
||
$requiredFiles = @(
|
||
"docker-compose.prod.yml",
|
||
"Dockerfile",
|
||
"package.json"
|
||
)
|
||
|
||
foreach ($file in $requiredFiles) {
|
||
$filePath = Join-Path $projectPath $file
|
||
if (-not (Test-Path $filePath)) {
|
||
Write-Host "❌ 缺少必要文件: $file" -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
}
|
||
Write-Host "✅ 必要文件检查通过" -ForegroundColor Green
|
||
|
||
# 测试SSH连接
|
||
Write-Host "`n测试SSH连接..." -ForegroundColor Yellow
|
||
$sshTest = ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 "$ServerUser@$ServerIP" "echo 'SSH连接成功'" 2>&1
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Host "❌ SSH连接失败" -ForegroundColor Red
|
||
Write-Host "请检查:" -ForegroundColor Yellow
|
||
Write-Host " 1. 服务器IP地址是否正确: $ServerIP" -ForegroundColor Gray
|
||
Write-Host " 2. 用户名和密码是否正确" -ForegroundColor Gray
|
||
Write-Host " 3. 服务器是否可访问" -ForegroundColor Gray
|
||
Write-Host "`n提示: 首次连接可能需要手动输入密码" -ForegroundColor Yellow
|
||
exit 1
|
||
}
|
||
Write-Host "✅ SSH连接成功" -ForegroundColor Green
|
||
|
||
# 上传文件(如果未跳过)
|
||
if (-not $SkipUpload) {
|
||
Write-Host "`n上传项目文件到服务器..." -ForegroundColor Yellow
|
||
|
||
# 创建临时压缩包
|
||
$tempZip = "$env:TEMP\furniture-3d-system-$(Get-Date -Format 'yyyyMMdd-HHmmss').zip"
|
||
Write-Host "创建临时压缩包: $tempZip" -ForegroundColor Gray
|
||
|
||
# 排除不需要的文件
|
||
$excludePatterns = @(
|
||
"node_modules",
|
||
".next",
|
||
".git",
|
||
"backups",
|
||
"*.log"
|
||
)
|
||
|
||
# 使用PowerShell压缩(需要.NET 4.5+)
|
||
try {
|
||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||
[System.IO.Compression.ZipFile]::CreateFromDirectory($projectPath, $tempZip)
|
||
Write-Host "✅ 压缩包创建成功" -ForegroundColor Green
|
||
} catch {
|
||
Write-Host "❌ 压缩失败: $_" -ForegroundColor Red
|
||
Write-Host "请手动打包项目文件并上传到服务器" -ForegroundColor Yellow
|
||
exit 1
|
||
}
|
||
|
||
# 上传压缩包
|
||
Write-Host "上传压缩包到服务器..." -ForegroundColor Gray
|
||
if ($useScp) {
|
||
# 使用SCP上传
|
||
scp -o StrictHostKeyChecking=no "$tempZip" "${ServerUser}@${ServerIP}:${RemotePath}.zip" 2>&1 | Out-Null
|
||
} else {
|
||
# 使用SSH + base64传输(备用方案)
|
||
Write-Host "⚠️ SCP不可用,请手动上传压缩包到服务器" -ForegroundColor Yellow
|
||
Write-Host "压缩包位置: $tempZip" -ForegroundColor Gray
|
||
Write-Host "服务器路径: $RemotePath.zip" -ForegroundColor Gray
|
||
$manualUpload = Read-Host "已手动上传?(Y/N)"
|
||
if ($manualUpload -ne 'Y' -and $manualUpload -ne 'y') {
|
||
exit 0
|
||
}
|
||
}
|
||
|
||
if ($LASTEXITCODE -eq 0 -or $manualUpload -eq 'Y' -or $manualUpload -eq 'y') {
|
||
Write-Host "✅ 文件上传成功" -ForegroundColor Green
|
||
|
||
# 在服务器上解压
|
||
Write-Host "在服务器上解压文件..." -ForegroundColor Gray
|
||
ssh -o StrictHostKeyChecking=no "$ServerUser@$ServerIP" "mkdir -p $RemotePath && unzip -q -o ${RemotePath}.zip -d $RemotePath && rm ${RemotePath}.zip" 2>&1 | Out-Null
|
||
|
||
Write-Host "✅ 文件解压完成" -ForegroundColor Green
|
||
} else {
|
||
Write-Host "❌ 文件上传失败" -ForegroundColor Red
|
||
Write-Host "请手动上传项目文件到服务器: $RemotePath" -ForegroundColor Yellow
|
||
exit 1
|
||
}
|
||
|
||
# 清理临时文件
|
||
Remove-Item $tempZip -ErrorAction SilentlyContinue
|
||
} else {
|
||
Write-Host "`n跳过文件上传(使用 -SkipUpload 参数)" -ForegroundColor Yellow
|
||
}
|
||
|
||
# 在服务器上执行部署
|
||
Write-Host "`n在服务器上执行部署..." -ForegroundColor Yellow
|
||
|
||
# 创建部署脚本(使用单引号here-string避免PowerShell解析bash变量)
|
||
$deployScript = @'
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
REMOTE_PATH="'@ + $RemotePath + @'"
|
||
SERVER_IP="'@ + $ServerIP + @'"
|
||
|
||
cd "$REMOTE_PATH"
|
||
|
||
echo "=== 检查Docker环境 ==="
|
||
docker --version || { echo "❌ Docker未安装"; exit 1; }
|
||
docker-compose --version || { echo "❌ Docker Compose未安装"; exit 1; }
|
||
|
||
echo "=== 检查环境变量文件 ==="
|
||
if [ ! -f .env ]; then
|
||
echo "⚠️ .env文件不存在,创建默认配置..."
|
||
cat > .env << EOF
|
||
DATABASE_URL=postgresql://furniture:furniture123@postgres:5432/furniture_db?schema=public
|
||
S3_ENDPOINT=http://minio:9000
|
||
S3_PUBLIC_ENDPOINT=http://${SERVER_IP}:9000
|
||
S3_REGION=us-east-1
|
||
S3_ACCESS_KEY=minioadmin
|
||
S3_SECRET_KEY=minioadmin123
|
||
S3_BUCKET=furniture-3d-models
|
||
JWT_SECRET=change-me-in-production-use-strong-random-string
|
||
NODE_ENV=production
|
||
NEXT_TELEMETRY_DISABLED=1
|
||
PORT=3000
|
||
WEB_PORT=3000
|
||
EOF
|
||
echo "✅ 已创建默认.env文件"
|
||
echo "⚠️ 请修改.env文件中的JWT_SECRET为强密码!"
|
||
else
|
||
echo "✅ .env文件已存在"
|
||
fi
|
||
|
||
echo "=== 停止现有服务 ==="
|
||
docker-compose -f docker-compose.prod.yml down || true
|
||
|
||
echo "=== 构建并启动服务 ==="
|
||
if [ "$SKIP_BUILD" = "true" ]; then
|
||
echo "跳过构建,直接启动..."
|
||
docker-compose -f docker-compose.prod.yml up -d
|
||
else
|
||
echo "构建应用镜像..."
|
||
docker-compose -f docker-compose.prod.yml build app
|
||
echo "启动所有服务..."
|
||
docker-compose -f docker-compose.prod.yml up -d
|
||
fi
|
||
|
||
echo "=== 等待服务启动 ==="
|
||
sleep 10
|
||
|
||
echo "=== 检查服务状态 ==="
|
||
docker-compose -f docker-compose.prod.yml ps
|
||
|
||
echo "=== 检查健康状态 ==="
|
||
sleep 5
|
||
curl -f http://localhost:3000/api/health || echo "⚠️ 健康检查失败,请查看日志"
|
||
|
||
echo ""
|
||
echo "=== 部署完成 ==="
|
||
echo "访问地址: http://${SERVER_IP}:3001"
|
||
echo "MinIO控制台: http://${SERVER_IP}:9003"
|
||
echo ""
|
||
echo "查看日志: docker-compose -f docker-compose.prod.yml logs -f"
|
||
'@
|
||
|
||
# 将部署脚本写入临时文件并上传
|
||
$scriptFile = "$env:TEMP\deploy-feiniu-$(Get-Date -Format 'yyyyMMdd-HHmmss').sh"
|
||
$deployScript | Out-File -FilePath $scriptFile -Encoding UTF8
|
||
|
||
Write-Host "上传部署脚本..." -ForegroundColor Gray
|
||
if ($useScp) {
|
||
scp -o StrictHostKeyChecking=no "$scriptFile" "${ServerUser}@${ServerIP}:/tmp/deploy-feiniu.sh" 2>&1 | Out-Null
|
||
} else {
|
||
Write-Host "⚠️ 请手动上传部署脚本到服务器: $scriptFile" -ForegroundColor Yellow
|
||
$manualScript = Read-Host "已手动上传?(Y/N)"
|
||
if ($manualScript -ne 'Y' -and $manualScript -ne 'y') {
|
||
exit 0
|
||
}
|
||
}
|
||
|
||
# 执行部署脚本
|
||
Write-Host "执行部署脚本..." -ForegroundColor Gray
|
||
$buildFlag = if ($SkipBuild) { "true" } else { "false" }
|
||
ssh -o StrictHostKeyChecking=no "$ServerUser@$ServerIP" "chmod +x /tmp/deploy-feiniu.sh && SKIP_BUILD=$buildFlag bash /tmp/deploy-feiniu.sh"
|
||
|
||
if ($LASTEXITCODE -eq 0) {
|
||
Write-Host "`n✅ 部署完成!" -ForegroundColor Green
|
||
Write-Host "`n访问地址:" -ForegroundColor Cyan
|
||
Write-Host " 应用: http://$ServerIP:3000" -ForegroundColor White
|
||
Write-Host " MinIO控制台: http://$ServerIP:9001" -ForegroundColor White
|
||
Write-Host "`n常用命令:" -ForegroundColor Cyan
|
||
Write-Host " 查看日志: ssh $ServerUser@$ServerIP 'cd $RemotePath && docker-compose -f docker-compose.prod.yml logs -f'" -ForegroundColor Gray
|
||
Write-Host " 查看状态: ssh $ServerUser@$ServerIP 'cd $RemotePath && docker-compose -f docker-compose.prod.yml ps'" -ForegroundColor Gray
|
||
Write-Host " 停止服务: ssh $ServerUser@$ServerIP 'cd $RemotePath && docker-compose -f docker-compose.prod.yml down'" -ForegroundColor Gray
|
||
} else {
|
||
Write-Host "`n❌ 部署过程中出现错误" -ForegroundColor Red
|
||
Write-Host "请查看服务器日志进行排查" -ForegroundColor Yellow
|
||
exit 1
|
||
}
|
||
|
||
# 清理临时文件
|
||
Remove-Item $scriptFile -ErrorAction SilentlyContinue
|
||
|
||
Write-Host "`n✅ 脚本执行完成!" -ForegroundColor Green
|