306 lines
10 KiB
PowerShell
306 lines
10 KiB
PowerShell
|
|
# ==========================================
|
|||
|
|
# 一键部署脚本 - 电商系统
|
|||
|
|
# 本地: Windows
|
|||
|
|
# 远程: Ubuntu Server (8.140.194.184)
|
|||
|
|
# 创建时间: 2025-11-27
|
|||
|
|
# ==========================================
|
|||
|
|
|
|||
|
|
param(
|
|||
|
|
[switch]$SkipWeb,
|
|||
|
|
[switch]$SkipAdmin,
|
|||
|
|
[switch]$SkipServer
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 配置信息
|
|||
|
|
$SSH_HOST = "8.140.194.184"
|
|||
|
|
$SSH_USER = "root"
|
|||
|
|
$SSH_PASSWORD = "7aK_H2yvokVuZ5HtL5Qrwl19m7L"
|
|||
|
|
$SSH_PORT = 22
|
|||
|
|
|
|||
|
|
# 本地路径
|
|||
|
|
$LOCAL_WEB = "web"
|
|||
|
|
$LOCAL_ADMIN = "admin"
|
|||
|
|
$LOCAL_SERVER = "server"
|
|||
|
|
|
|||
|
|
# 远程路径
|
|||
|
|
$REMOTE_WEB = "/home/work/ai_vizee"
|
|||
|
|
$REMOTE_ADMIN = "/home/work/ai_mis"
|
|||
|
|
$REMOTE_SERVER = "/home/work/ai_dianshang"
|
|||
|
|
|
|||
|
|
# 临时文件夹
|
|||
|
|
$TEMP_DIR = Join-Path $env:TEMP "dianshang_deploy"
|
|||
|
|
if (Test-Path $TEMP_DIR) {
|
|||
|
|
Remove-Item $TEMP_DIR -Recurse -Force
|
|||
|
|
}
|
|||
|
|
New-Item -ItemType Directory -Path $TEMP_DIR | Out-Null
|
|||
|
|
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
Write-Host " 电商系统一键部署工具" -ForegroundColor Cyan
|
|||
|
|
Write-Host " 目标服务器: $SSH_HOST (Ubuntu)" -ForegroundColor Cyan
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
Write-Host ""
|
|||
|
|
|
|||
|
|
# 检查工具函数
|
|||
|
|
function Test-Command {
|
|||
|
|
param($Command)
|
|||
|
|
try {
|
|||
|
|
if (Get-Command $Command -ErrorAction Stop) {
|
|||
|
|
return $true
|
|||
|
|
}
|
|||
|
|
} catch {
|
|||
|
|
return $false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Write-Host "[检查] 检查必要工具..." -ForegroundColor Yellow
|
|||
|
|
|
|||
|
|
# 检查 SSH 工具 (优先使用 plink,其次使用 ssh)
|
|||
|
|
$USE_PLINK = $false
|
|||
|
|
$USE_PSCP = $false
|
|||
|
|
|
|||
|
|
if (Test-Command "plink") {
|
|||
|
|
Write-Host "[成功] 找到 PuTTY plink" -ForegroundColor Green
|
|||
|
|
$USE_PLINK = $true
|
|||
|
|
} elseif (Test-Command "ssh") {
|
|||
|
|
Write-Host "[成功] 找到 OpenSSH" -ForegroundColor Green
|
|||
|
|
$USE_PLINK = $false
|
|||
|
|
} else {
|
|||
|
|
Write-Host "[错误] 未找到 SSH 工具 (plink 或 ssh)" -ForegroundColor Red
|
|||
|
|
Write-Host "请安装以下任一工具:" -ForegroundColor Yellow
|
|||
|
|
Write-Host " 1. PuTTY (推荐): https://www.putty.org/" -ForegroundColor Yellow
|
|||
|
|
Write-Host " 2. OpenSSH: 设置 -> 应用 -> 可选功能 -> OpenSSH 客户端" -ForegroundColor Yellow
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (Test-Command "pscp") {
|
|||
|
|
Write-Host "[成功] 找到 PuTTY pscp" -ForegroundColor Green
|
|||
|
|
$USE_PSCP = $true
|
|||
|
|
} elseif (Test-Command "scp") {
|
|||
|
|
Write-Host "[成功] 找到 OpenSSH scp" -ForegroundColor Green
|
|||
|
|
$USE_PSCP = $false
|
|||
|
|
} else {
|
|||
|
|
Write-Host "[错误] 未找到 SCP 工具 (pscp 或 scp)" -ForegroundColor Red
|
|||
|
|
Write-Host "请安装以下任一工具:" -ForegroundColor Yellow
|
|||
|
|
Write-Host " 1. PuTTY (推荐): https://www.putty.org/" -ForegroundColor Yellow
|
|||
|
|
Write-Host " 2. OpenSSH: 设置 -> 应用 -> 可选功能 -> OpenSSH 客户端" -ForegroundColor Yellow
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Write-Host ""
|
|||
|
|
|
|||
|
|
# SSH 执行命令函数
|
|||
|
|
function Invoke-SSHCommand {
|
|||
|
|
param($Command)
|
|||
|
|
|
|||
|
|
Write-Host "[SSH] 执行命令: $Command" -ForegroundColor Cyan
|
|||
|
|
|
|||
|
|
if ($USE_PLINK) {
|
|||
|
|
# 使用 PuTTY plink
|
|||
|
|
echo y | plink -ssh -pw $SSH_PASSWORD ${SSH_USER}@${SSH_HOST} -P $SSH_PORT $Command 2>&1
|
|||
|
|
} else {
|
|||
|
|
# 使用 OpenSSH (需要配置 sshpass 或手动输入密码)
|
|||
|
|
# 创建临时的 SSH 配置来避免主机密钥检查
|
|||
|
|
$env:SSH_ASKPASS = ""
|
|||
|
|
ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -p $SSH_PORT ${SSH_USER}@${SSH_HOST} $Command 2>&1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null) {
|
|||
|
|
Write-Host "[警告] SSH 命令返回码: $LASTEXITCODE" -ForegroundColor Yellow
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# SCP 上传文件函数
|
|||
|
|
function Copy-ToRemote {
|
|||
|
|
param($LocalFile, $RemotePath)
|
|||
|
|
|
|||
|
|
Write-Host "[上传] $LocalFile" -ForegroundColor Cyan
|
|||
|
|
Write-Host " -> ${SSH_HOST}:${RemotePath}" -ForegroundColor Cyan
|
|||
|
|
|
|||
|
|
if ($USE_PSCP) {
|
|||
|
|
# 使用 PuTTY pscp
|
|||
|
|
echo y | pscp -pw $SSH_PASSWORD -P $SSH_PORT $LocalFile ${SSH_USER}@${SSH_HOST}:${RemotePath} 2>&1
|
|||
|
|
} else {
|
|||
|
|
# 使用 OpenSSH scp
|
|||
|
|
scp -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -P $SSH_PORT $LocalFile ${SSH_USER}@${SSH_HOST}:${RemotePath} 2>&1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null) {
|
|||
|
|
Write-Host "[错误] 文件上传失败 (退出码: $LASTEXITCODE)" -ForegroundColor Red
|
|||
|
|
return $false
|
|||
|
|
}
|
|||
|
|
Write-Host "[成功] 文件上传完成" -ForegroundColor Green
|
|||
|
|
return $true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ==========================================
|
|||
|
|
# 1. 部署 Web 项目
|
|||
|
|
# ==========================================
|
|||
|
|
if (-not $SkipWeb) {
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
Write-Host " [1/3] 部署 Web 项目" -ForegroundColor Cyan
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $LOCAL_WEB)) {
|
|||
|
|
Write-Host "[错误] 未找到 web 文件夹" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 压缩 web 文件夹
|
|||
|
|
$webZip = Join-Path $TEMP_DIR "web.zip"
|
|||
|
|
Write-Host "[压缩] 压缩 web 文件夹..." -ForegroundColor Yellow
|
|||
|
|
|
|||
|
|
# 使用 PowerShell 内置压缩
|
|||
|
|
Compress-Archive -Path "$LOCAL_WEB\*" -DestinationPath $webZip -Force
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $webZip)) {
|
|||
|
|
Write-Host "[错误] web 压缩失败" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
$fileSize = [math]::Round((Get-Item $webZip).Length / 1MB, 2)
|
|||
|
|
Write-Host "[成功] web 压缩完成 ($fileSize MB)" -ForegroundColor Green
|
|||
|
|
|
|||
|
|
# 上传到服务器
|
|||
|
|
if (-not (Copy-ToRemote $webZip "/tmp/web.zip")) {
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 解压并覆盖
|
|||
|
|
Write-Host "[解压] 解压 web 到 $REMOTE_WEB..." -ForegroundColor Yellow
|
|||
|
|
Invoke-SSHCommand "mkdir -p $REMOTE_WEB && cd $REMOTE_WEB && rm -rf * && unzip -o /tmp/web.zip && rm -f /tmp/web.zip"
|
|||
|
|
|
|||
|
|
Write-Host "[完成] Web 项目部署完成!" -ForegroundColor Green
|
|||
|
|
Write-Host ""
|
|||
|
|
} else {
|
|||
|
|
Write-Host "[跳过] 跳过 Web 项目部署" -ForegroundColor Yellow
|
|||
|
|
Write-Host ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ==========================================
|
|||
|
|
# 2. 部署 Admin 项目
|
|||
|
|
# ==========================================
|
|||
|
|
if (-not $SkipAdmin) {
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
Write-Host " [2/3] 部署 Admin 项目" -ForegroundColor Cyan
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $LOCAL_ADMIN)) {
|
|||
|
|
Write-Host "[错误] 未找到 admin 文件夹" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 执行 npm build
|
|||
|
|
Write-Host "[构建] 执行 npm run build:prod..." -ForegroundColor Yellow
|
|||
|
|
Push-Location $LOCAL_ADMIN
|
|||
|
|
|
|||
|
|
# 检测 npm 命令
|
|||
|
|
$npmCommand = "npm"
|
|||
|
|
if (Test-Command "npm.cmd") {
|
|||
|
|
$npmCommand = "npm.cmd"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
& $npmCommand run build:prod
|
|||
|
|
|
|||
|
|
if ($LASTEXITCODE -ne 0) {
|
|||
|
|
Write-Host "[错误] npm build 失败" -ForegroundColor Red
|
|||
|
|
Pop-Location
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
Pop-Location
|
|||
|
|
Write-Host "[成功] Admin 构建完成" -ForegroundColor Green
|
|||
|
|
|
|||
|
|
# 检查 dist 文件夹
|
|||
|
|
$distPath = Join-Path $LOCAL_ADMIN "dist"
|
|||
|
|
if (-not (Test-Path $distPath)) {
|
|||
|
|
Write-Host "[错误] 未找到 dist 文件夹" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 压缩 dist 文件夹
|
|||
|
|
$adminZip = Join-Path $TEMP_DIR "admin.zip"
|
|||
|
|
Write-Host "[压缩] 压缩 dist 文件夹..." -ForegroundColor Yellow
|
|||
|
|
|
|||
|
|
Compress-Archive -Path "$distPath\*" -DestinationPath $adminZip -Force
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $adminZip)) {
|
|||
|
|
Write-Host "[错误] dist 压缩失败" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
$fileSize = [math]::Round((Get-Item $adminZip).Length / 1MB, 2)
|
|||
|
|
Write-Host "[成功] dist 压缩完成 ($fileSize MB)" -ForegroundColor Green
|
|||
|
|
|
|||
|
|
# 上传到服务器
|
|||
|
|
if (-not (Copy-ToRemote $adminZip "/tmp/admin.zip")) {
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 解压并覆盖
|
|||
|
|
Write-Host "[解压] 解压 dist 到 $REMOTE_ADMIN..." -ForegroundColor Yellow
|
|||
|
|
Invoke-SSHCommand "mkdir -p $REMOTE_ADMIN && cd $REMOTE_ADMIN && rm -rf * && unzip -o /tmp/admin.zip && rm -f /tmp/admin.zip"
|
|||
|
|
|
|||
|
|
Write-Host "[完成] Admin 项目部署完成!" -ForegroundColor Green
|
|||
|
|
Write-Host ""
|
|||
|
|
} else {
|
|||
|
|
Write-Host "[跳过] 跳过 Admin 项目部署" -ForegroundColor Yellow
|
|||
|
|
Write-Host ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ==========================================
|
|||
|
|
# 3. 部署 Server 项目
|
|||
|
|
# ==========================================
|
|||
|
|
if (-not $SkipServer) {
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
Write-Host " [3/3] 部署 Server 项目" -ForegroundColor Cyan
|
|||
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $LOCAL_SERVER)) {
|
|||
|
|
Write-Host "[错误] 未找到 server 文件夹" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 压缩 server 文件夹
|
|||
|
|
$serverZip = Join-Path $TEMP_DIR "server.zip"
|
|||
|
|
Write-Host "[压缩] 压缩 server 文件夹..." -ForegroundColor Yellow
|
|||
|
|
|
|||
|
|
Compress-Archive -Path "$LOCAL_SERVER\*" -DestinationPath $serverZip -Force
|
|||
|
|
|
|||
|
|
if (-not (Test-Path $serverZip)) {
|
|||
|
|
Write-Host "[错误] server 压缩失败" -ForegroundColor Red
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
$fileSize = [math]::Round((Get-Item $serverZip).Length / 1MB, 2)
|
|||
|
|
Write-Host "[成功] server 压缩完成 ($fileSize MB)" -ForegroundColor Green
|
|||
|
|
|
|||
|
|
# 上传到服务器
|
|||
|
|
if (-not (Copy-ToRemote $serverZip "/tmp/server.zip")) {
|
|||
|
|
exit 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 解压并覆盖
|
|||
|
|
Write-Host "[解压] 解压 server 到 $REMOTE_SERVER..." -ForegroundColor Yellow
|
|||
|
|
Invoke-SSHCommand "mkdir -p $REMOTE_SERVER && cd $REMOTE_SERVER && rm -rf * && unzip -o /tmp/server.zip && rm -f /tmp/server.zip"
|
|||
|
|
|
|||
|
|
# 执行 run.sh
|
|||
|
|
Write-Host "[启动] 执行 run.sh..." -ForegroundColor Yellow
|
|||
|
|
Invoke-SSHCommand "cd $REMOTE_SERVER && chmod +x run.sh && ./run.sh"
|
|||
|
|
|
|||
|
|
Write-Host "[完成] Server 项目部署完成!" -ForegroundColor Green
|
|||
|
|
Write-Host ""
|
|||
|
|
} else {
|
|||
|
|
Write-Host "[跳过] 跳过 Server 项目部署" -ForegroundColor Yellow
|
|||
|
|
Write-Host ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 清理临时文件
|
|||
|
|
Write-Host "[清理] 清理临时文件..." -ForegroundColor Yellow
|
|||
|
|
Remove-Item $TEMP_DIR -Recurse -Force
|
|||
|
|
|
|||
|
|
Write-Host "========================================" -ForegroundColor Green
|
|||
|
|
Write-Host " 🎉 部署完成!" -ForegroundColor Green
|
|||
|
|
Write-Host "========================================" -ForegroundColor Green
|
|||
|
|
Write-Host ""
|
|||
|
|
Write-Host "服务访问地址:" -ForegroundColor Cyan
|
|||
|
|
Write-Host " Web前端: http://$SSH_HOST" -ForegroundColor White
|
|||
|
|
Write-Host " Admin后台: http://$SSH_HOST/admin" -ForegroundColor White
|
|||
|
|
Write-Host " API服务: http://$SSH_HOST/api" -ForegroundColor White
|
|||
|
|
Write-Host ""
|