flnxi-Wu/deploy-new.ps1
WuYongJie f646b71813
Some checks failed
CI Check / check (push) Has been cancelled
chore: 初始化本地仓库并同步最近改动
2025-11-18 17:50:16 +08:00

416 lines
14 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ================================================================
# 新建简化部署脚本 - 处理SSH认证问题和本地构建上传
# 优化版部署脚本 - 支持自动SSH密钥处理和错误恢复
# ================================================================
# 处理参数
param(
[string]$Server = "45.249.208.118",
[string]$Username = "root",
[string]$Password = "",
[string]$KeyPath = "",
[string]$ImageName = "youyidian-3d-material",
[string]$Tag = "local-deploy",
[string]$LocalPath = "",
[string]$RemotePath = "/opt/deploy",
[switch]$SkipCheck,
[switch]$SkipBuild,
[switch]$SkipUpload,
[switch]$Force,
[switch]$Debug,
[switch]$Help
)
# 脚本配置
Set-StrictMode -Version Latest
$ErrorActionPreference = "Continue"
# 颜色输出函数
function Write-ColorOutput {
param(
[string]$Message,
[ConsoleColor]$ForegroundColor = "White"
)
Write-Host $Message -ForegroundColor $ForegroundColor
}
function Write-Success {
param([string]$Message)
Write-ColorOutput "✓ $Message" "Green"
}
function Write-Warning {
param([string]$Message)
Write-ColorOutput "⚠ $Message" "Yellow"
}
function Write-ErrorColored {
param([string]$Message)
Write-ColorOutput "✗ $Message" "Red"
}
function Write-Info {
param([string]$Message)
Write-ColorOutput "ℹ $Message" "Cyan"
}
# 文件大小格式化
function Format-FileSize {
param([long]$Size)
if ($Size -ge 1GB) {
return "{0:N2} GB" -f ($Size / 1GB)
} elseif ($Size -ge 1MB) {
return "{0:N2} MB" -f ($Size / 1MB)
} elseif ($Size -ge 1KB) {
return "{0:N2} KB" -f ($Size / 1KB)
} else {
return "$Size B"
}
}
# 检查命令是否存在
function Test-Command {
param([string]$Command)
try {
$null = Get-Command $Command -ErrorAction Stop
return $true
} catch {
return $false
}
}
# 查找SSH密钥文件
function Find-SSHKeys {
$possibleKeys = @(
"$env:USERPROFILE\.ssh\youyidian_prod_ed25519",
"$env:USERPROFILE\.ssh\id_rsa",
"$env:USERPROFILE\.ssh\id_ed25519",
"$env:USERPROFILE\.ssh\id_ecdsa",
"$env:USERPROFILE\.ssh\id_dsa"
)
$foundKeys = @()
foreach ($key in $possibleKeys) {
if (Test-Path $key) {
$foundKeys += $key
}
}
return $foundKeys
}
# 测试SSH连接
function Test-SSHConnection {
param(
[string]$Server,
[string]$Username,
[string]$Password = "",
[string]$KeyPath = ""
)
$sshArgs = @("-o", "BatchMode=yes", "-o", "ConnectTimeout=10")
$target = "${Username}@${Server}"
if ($KeyPath -and (Test-Path $KeyPath)) {
$sshArgs += @("-i", $KeyPath)
Write-Info "使用SSH密钥: $KeyPath"
} elseif ($Password) {
$sshArgs += @("-o", "PasswordAuthentication=yes")
Write-Info "使用密码认证"
} else {
Write-Warning "未提供密码或密钥,使用交互式认证"
$sshArgs += @("-o", "StrictHostKeyChecking=no")
}
try {
$process = Start-Process -FilePath "ssh" -ArgumentList ($sshArgs + @($target, "echo 'SSH连接测试成功'")) -NoNewWindow -PassThru -Wait -RedirectStandardOutput temp_stdout.txt -RedirectStandardError temp_stderr.txt
if ($process.ExitCode -eq 0) {
Write-Success "SSH连接测试成功"
return $true
} else {
$errorOutput = Get-Content temp_stderr.txt -ErrorAction SilentlyContinue
Write-ErrorColored "SSH连接失败: $errorOutput"
return $false
}
} catch {
Write-ErrorColored "SSH测试异常: $_"
return $false
} finally {
Remove-Item temp_stdout.txt, temp_stderr.txt -ErrorAction SilentlyContinue
}
}
# 上传文件
function Upload-File {
param(
[string]$LocalPath,
[string]$RemotePath,
[string]$Server,
[string]$Username,
[string]$Password = "",
[string]$KeyPath = ""
)
$remoteTarget = "${Username}@${Server}:${RemotePath}/"
$scpArgs = @("-o", "BatchMode=yes", "-o", "ConnectTimeout=30")
if ($KeyPath -and (Test-Path $KeyPath)) {
$scpArgs += @("-i", $KeyPath)
Write-Info "使用SSH密钥上传: $KeyPath"
} elseif ($Password) {
$scpArgs += @("-o", "PasswordAuthentication=yes")
Write-Info "使用密码上传"
} else {
Write-Warning "使用交互式上传"
$scpArgs += @("-o", "StrictHostKeyChecking=no")
}
try {
Write-Info "正在上传: $LocalPath -> $remoteTarget"
$process = Start-Process -FilePath "scp" -ArgumentList ($scpArgs + @($LocalPath, $remoteTarget)) -NoNewWindow -PassThru -Wait -RedirectStandardOutput temp_stdout.txt -RedirectStandardError temp_stderr.txt
if ($process.ExitCode -eq 0) {
Write-Success "文件上传成功"
return $true
} else {
$errorOutput = Get-Content temp_stderr.txt -ErrorAction SilentlyContinue
Write-ErrorColored "文件上传失败: $errorOutput"
return $false
}
} catch {
Write-ErrorColored "上传异常: $_"
return $false
} finally {
Remove-Item temp_stdout.txt, temp_stderr.txt -ErrorAction SilentlyContinue
}
}
# 主函数
function Main {
Write-ColorOutput "========================================" "Magenta"
Write-ColorOutput " 新建简化部署脚本 v1.0" "Magenta"
Write-ColorOutput "========================================" "Magenta"
# 显示配置
Write-Info "部署配置:"
Write-Info " 服务器: $Server"
Write-Info " 用户名: $Username"
Write-Info " 镜像: $ImageName`:$Tag"
Write-Info " 跳过检查: $SkipCheck"
Write-Info " 跳过构建: $SkipBuild"
Write-Info " 跳过上传: $SkipUpload"
Write-ColorOutput ""
# 检查必要工具
Write-Info "检查必要工具..."
$requiredTools = @("docker")
$missingTools = @()
foreach ($tool in $requiredTools) {
if (Test-Command $tool) {
Write-Success "$tool 已安装"
} else {
Write-ErrorColored "$tool 未安装"
$missingTools += $tool
}
}
if ($missingTools.Count -gt 0) {
Write-ErrorColored "缺少必要工具: $($missingTools -join ', ')"
exit 1
}
# 项目根目录
$projectRoot = Get-Location
Write-Info "项目目录: $projectRoot"
# 1. 检查阶段
if (-not $SkipCheck) {
Write-ColorOutput "===> 检查阶段" "Cyan"
Write-Info "运行 npm run check..."
try {
$process = Start-Process -FilePath "npm" -ArgumentList @("run", "check") -NoNewWindow -PassThru -Wait
if ($process.ExitCode -ne 0) {
Write-Warning "npm run check 有警告,但继续执行"
} else {
Write-Success "代码检查通过"
}
} catch {
Write-Warning "检查阶段异常: $_"
}
}
# 2. 构建阶段
$fullImage = "${ImageName}:${Tag}"
if (-not $SkipBuild) {
Write-ColorOutput "===> 构建阶段" "Cyan"
Write-Info "开始Docker构建: $fullImage"
# 构建参数
$buildArgs = @(
"build",
"-t", $fullImage,
"-f", "Dockerfile",
"--build-arg", "DATABASE_URL=postgresql://placeholder:placeholder@localhost:5432/placeholder",
"--build-arg", "NEXTAUTH_URL=http://$Server:4320",
"--build-arg", "APP_PUBLIC_URL=http://$Server:4320",
"."
)
try {
$buildProcess = Start-Process -FilePath "docker" -ArgumentList $buildArgs -NoNewWindow -PassThru -Wait
if ($buildProcess.ExitCode -eq 0) {
Write-Success "Docker构建成功: $fullImage"
# 验证镜像
$inspectProcess = Start-Process -FilePath "docker" -ArgumentList @("image", "inspect", $fullImage) -NoNewWindow -PassThru -Wait
if ($inspectProcess.ExitCode -eq 0) {
Write-Success "镜像验证成功"
} else {
Write-ErrorColored "镜像验证失败"
exit 1
}
} else {
Write-ErrorColored "Docker构建失败"
exit 1
}
} catch {
Write-ErrorColored "构建过程异常: $_"
exit 1
}
} else {
Write-Warning "跳过构建,使用现有镜像: $fullImage"
}
# 3. 打包阶段
if (-not $SkipUpload) {
Write-ColorOutput "===> 打包阶段" "Cyan"
$archiveDir = Join-Path $projectRoot "deploy-artifacts"
if (-not (Test-Path $archiveDir)) {
New-Item -ItemType Directory -Path $archiveDir | Out-Null
Write-Success "创建打包目录: $archiveDir"
}
$timestamp = Get-Date -Format "yyyyMMddHHmmss"
$safeName = $ImageName -replace '[\\/]', '_'
$archivePath = Join-Path $archiveDir "$safeName-$Tag-$timestamp.tar"
Write-Info "正在打包镜像..."
Write-Info "目标文件: $archivePath"
try {
$saveProcess = Start-Process -FilePath "docker" -ArgumentList @("save", "-o", $archivePath, $fullImage) -NoNewWindow -PassThru -Wait
if ($saveProcess.ExitCode -eq 0) {
if (Test-Path $archivePath) {
$fileSize = (Get-Item $archivePath).Length
Write-Success "镜像打包完成: $(Format-FileSize $fileSize)"
$LocalPath = $archivePath
} else {
Write-ErrorColored "打包文件未生成"
exit 1
}
} else {
Write-ErrorColored "镜像打包失败"
exit 1
}
} catch {
Write-ErrorColored "打包过程异常: $_"
exit 1
}
}
# 4. 上传阶段
if (-not $SkipUpload) {
Write-ColorOutput "===> 上传阶段" "Cyan"
# 寻找SSH密钥
if ([string]::IsNullOrWhiteSpace($KeyPath)) {
Write-Info "查找SSH密钥..."
$sshKeys = Find-SSHKeys
if ($sshKeys.Count -gt 0) {
$KeyPath = $sshKeys[0]
Write-Success "找到SSH密钥: $KeyPath"
} else {
Write-Warning "未找到SSH密钥文件"
}
}
# 测试SSH连接
Write-Info "测试SSH连接..."
$sshTest = Test-SSHConnection -Server $Server -Username $Username -Password $Password -KeyPath $KeyPath
if (-not $sshTest) {
Write-ErrorColored "SSH连接测试失败,请检查配置"
Write-Info "提示: 可以使用 -KeyPath 指定密钥文件或 -Password 指定密码"
exit 1
}
# 上传文件
if (-not [string]::IsNullOrWhiteSpace($LocalPath) -and (Test-Path $LocalPath)) {
Write-Info "开始上传文件..."
$uploadSuccess = Upload-File -LocalPath $LocalPath -RemotePath $RemotePath -Server $Server -Username $Username -Password $Password -KeyPath $KeyPath
if ($uploadSuccess) {
Write-Success "文件上传成功"
} else {
Write-ErrorColored "文件上传失败"
exit 1
}
} else {
Write-ErrorColored "未找到要上传的文件: $LocalPath"
exit 1
}
}
Write-ColorOutput "" "Magenta"
Write-ColorOutput "========================================" "Magenta"
Write-ColorOutput " 部署完成!" "Magenta"
Write-ColorOutput "========================================" "Magenta"
Write-Success "所有阶段执行成功"
Write-Info "镜像: $fullImage"
Write-Info "服务器: ${Username}@${Server}"
Write-Info "远程路径: $RemotePath"
if (-not $SkipUpload) {
Write-Info "下一步请在服务器上运行:"
Write-Info " cd $RemotePath"
Write-Info " docker load < $([System.IO.Path]::GetFileName($LocalPath))"
Write-Info " docker-compose up -d"
}
}
# 检查是否需要显示帮助
if ($Help -or $args.Count -eq 0) {
Write-ColorOutput "新建简化部署脚本" "Green"
Write-ColorOutput "========================================" "Green"
Write-ColorOutput "用法:" "White"
Write-ColorOutput " .\deploy-new.ps1 [参数]" "Yellow"
Write-ColorOutput "" "White"
Write-ColorOutput "参数:" "White"
Write-ColorOutput " -Server <地址> 服务器地址 (默认: 45.249.208.118)" "Gray"
Write-ColorOutput " -Username <用户> SSH用户名 (默认: root)" "Gray"
Write-ColorOutput " -Password <密码> SSH密码" "Gray"
Write-ColorOutput " -KeyPath <路径> SSH私钥路径" "Gray"
Write-ColorOutput " -SkipCheck 跳过代码检查" "Gray"
Write-ColorOutput " -SkipBuild 跳过Docker构建" "Gray"
Write-ColorOutput " -SkipUpload 跳过文件上传" "Gray"
Write-ColorOutput " -Debug 启用调试模式" "Gray"
Write-ColorOutput " -Help 显示此帮助信息" "Gray"
Write-ColorOutput "" "White"
Write-ColorOutput "示例:" "White"
Write-ColorOutput " .\deploy-new.ps1" "Yellow"
Write-ColorOutput " .\deploy-new.ps1 -Password 'your-password'" "Yellow"
Write-ColorOutput " .\deploy-new.ps1 -KeyPath 'C:\Users\.ssh\id_rsa'" "Yellow"
Write-ColorOutput " .\deploy-new.ps1 -SkipCheck -SkipUpload" "Yellow"
exit 0
}
# 执行主函数
Main