94 lines
3.7 KiB
PowerShell
94 lines
3.7 KiB
PowerShell
<#
|
||
.SYNOPSIS
|
||
构建 → 自检 → 发布 → 部署到服务器 → 验证,一条命令完成 WpywMail 更新。
|
||
|
||
.EXAMPLE
|
||
.\deploy.ps1 -Server <SERVER_IP> -RemotePassword '***'
|
||
.\deploy.ps1 -Server <SERVER_IP> -RemotePassword '***' -FullCopy # 首次部署或运行时变更时用
|
||
#>
|
||
[CmdletBinding()]
|
||
param(
|
||
[Parameter(Mandatory)][string]$Server,
|
||
[string]$RemoteUser = 'Administrator',
|
||
[string]$RemotePassword,
|
||
[string]$RemotePath = 'C:\Program Files\WpywMail',
|
||
[string]$TaskName = 'WpywMail',
|
||
[switch]$FullCopy,
|
||
[switch]$SkipTests
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
$root = Split-Path -Parent $PSScriptRoot
|
||
$publish = Join-Path (Split-Path -Parent $root) 'work\publish-v2'
|
||
|
||
function Step($text) { Write-Host "`n=== $text ===" -ForegroundColor Cyan }
|
||
|
||
Step '1) 构建'
|
||
Push-Location $root
|
||
try {
|
||
& dotnet build -c Release -v q --nologo
|
||
if ($LASTEXITCODE -ne 0) { throw '构建失败' }
|
||
|
||
$exe = Join-Path $root 'bin\Release\net8.0\win-x64\WpywMail.Native.exe'
|
||
|
||
if (-not $SkipTests) {
|
||
Step '2) 自检'
|
||
& $exe --selftest
|
||
if ($LASTEXITCODE -ne 0) { throw '自检未通过,已中止部署' }
|
||
}
|
||
|
||
Step '3) 发布(自包含 win-x64)'
|
||
& dotnet publish -c Release -r win-x64 --self-contained true -v q --nologo -o $publish
|
||
if ($LASTEXITCODE -ne 0) { throw '发布失败' }
|
||
} finally { Pop-Location }
|
||
|
||
if ($RemotePassword) {
|
||
$sec = ConvertTo-SecureString $RemotePassword -AsPlainText -Force
|
||
$cred = New-Object System.Management.Automation.PSCredential("$Server\$RemoteUser", $sec)
|
||
} else {
|
||
$cred = Get-Credential -UserName "$Server\$RemoteUser" -Message "连接 $Server 的凭据"
|
||
}
|
||
|
||
Step '4) 停服务'
|
||
$session = New-PSSession -ComputerName $Server -Credential $cred
|
||
try {
|
||
Invoke-Command -Session $session -ArgumentList $TaskName -ScriptBlock {
|
||
param($task)
|
||
Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue
|
||
Start-Sleep -Seconds 3
|
||
Get-CimInstance Win32_Process -Filter "Name='WpywMail.Native.exe'" |
|
||
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
|
||
}
|
||
|
||
Step '5) 传输文件'
|
||
if ($FullCopy) {
|
||
Write-Host ' 全量复制(首次部署或运行时版本变更时使用)'
|
||
Copy-Item -Path "$publish\*" -Destination $RemotePath -ToSession $session -Recurse -Force
|
||
} else {
|
||
Write-Host ' 增量复制(仅程序集,约 400 KB)'
|
||
foreach ($f in 'WpywMail.Native.dll', 'WpywMail.Native.exe', 'WpywMail.Native.pdb', 'WpywMail.Native.deps.json') {
|
||
Copy-Item -Path (Join-Path $publish $f) -Destination "$RemotePath\" -ToSession $session -Force
|
||
}
|
||
}
|
||
|
||
Step '6) 启动并验证'
|
||
Invoke-Command -Session $session -ArgumentList $TaskName, $RemotePath -ScriptBlock {
|
||
param($task, $path)
|
||
# 启动前在服务器上再跑一次自检,确保部署的就是通过测试的二进制
|
||
& (Join-Path $path 'WpywMail.Native.exe') --selftest | Select-String -Pattern '失败|=== 结果'
|
||
Start-ScheduledTask -TaskName $task
|
||
Start-Sleep -Seconds 7
|
||
$p = Get-CimInstance Win32_Process -Filter "Name='WpywMail.Native.exe'"
|
||
if (-not $p) { throw '服务未能启动' }
|
||
" 运行中 PID: $($p.ProcessId)"
|
||
Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |
|
||
Where-Object { $_.LocalPort -in 25, 587, 8787 } |
|
||
ForEach-Object { " 监听 {0}:{1}" -f $_.LocalAddress, $_.LocalPort }
|
||
Get-Content 'C:\WpywMailData\service.log' -Tail 4 -Encoding UTF8
|
||
}
|
||
} finally {
|
||
Remove-PSSession $session
|
||
}
|
||
|
||
Write-Host "`n部署完成。回滚:把 $RemotePath 换回 $RemotePath.v1-backup 并重启计划任务 $TaskName。" -ForegroundColor Green
|