上传源代码版本
This commit is contained in:
90
deployment/scripts/build-and-publish.ps1
Normal file
90
deployment/scripts/build-and-publish.ps1
Normal file
@@ -0,0 +1,90 @@
|
||||
param(
|
||||
[string]$OutputDirectory = "D:\EPproject\LabelReplaceServer\deployment\green",
|
||||
[string]$Version = (Get-Date -Format "yyyyMMdd-HHmmss"),
|
||||
[string]$Configuration = "Release"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$projectPath = "D:\EPproject\LabelReplaceServer\src\CONTROLLER\CONTROLLER.csproj"
|
||||
$logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log"
|
||||
$backupDir = "D:\EPproject\LabelReplaceServer\deployment\backups"
|
||||
|
||||
function Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] $Message"
|
||||
Write-Host $logEntry
|
||||
|
||||
$logDirPath = Split-Path -Parent $logFile
|
||||
if (!(Test-Path $logDirPath)) {
|
||||
New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
|
||||
}
|
||||
Add-Content -Path $logFile -Value $logEntry
|
||||
}
|
||||
|
||||
try {
|
||||
Log "========================================" "INFO"
|
||||
Log "开始编译和发布应用..." "INFO"
|
||||
Log "版本: $Version" "INFO"
|
||||
Log "输出目录: $OutputDirectory" "INFO"
|
||||
Log "配置: $Configuration" "INFO"
|
||||
Log "========================================" "INFO"
|
||||
|
||||
if (!(Test-Path $projectPath)) {
|
||||
throw "项目文件不存在: $projectPath"
|
||||
}
|
||||
|
||||
if (Test-Path $OutputDirectory) {
|
||||
Log "创建输出目录备份..." "INFO"
|
||||
if (!(Test-Path $backupDir)) {
|
||||
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$backupName = "backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
||||
$backupPath = Join-Path $backupDir $backupName
|
||||
Copy-Item -Path $OutputDirectory -Destination $backupPath -Recurse -Force
|
||||
Log "备份已保存到: $backupPath" "INFO"
|
||||
}
|
||||
|
||||
Log "清理旧的输出目录..." "INFO"
|
||||
if (Test-Path $OutputDirectory) {
|
||||
Remove-Item -Path $OutputDirectory -Recurse -Force
|
||||
}
|
||||
|
||||
Log "执行 dotnet clean..." "INFO"
|
||||
& dotnet clean $projectPath -c $Configuration --nologo
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet clean 失败,退出代码: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Log "执行 dotnet restore..." "INFO"
|
||||
& dotnet restore $projectPath --nologo
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet restore 失败,退出代码: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Log "执行 dotnet build..." "INFO"
|
||||
& dotnet build $projectPath -c $Configuration --nologo --no-restore
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet build 失败,退出代码: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Log "执行 dotnet publish..." "INFO"
|
||||
& dotnet publish $projectPath -c $Configuration -o $OutputDirectory --nologo --no-build
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet publish 失败,退出代码: $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Log "========================================" "INFO"
|
||||
Log "编译和发布完成!" "INFO"
|
||||
Log "输出位置: $OutputDirectory" "INFO"
|
||||
Log "========================================" "INFO"
|
||||
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Log "编译和发布失败: $_" "ERROR"
|
||||
Log "错误详情: $($_.Exception.StackTrace)" "ERROR"
|
||||
return $false
|
||||
}
|
||||
209
deployment/scripts/deploy-blue-green.ps1
Normal file
209
deployment/scripts/deploy-blue-green.ps1
Normal file
@@ -0,0 +1,209 @@
|
||||
param(
|
||||
[string]$Version = (Get-Date -Format "yyyyMMdd-HHmmss"),
|
||||
[string]$TargetInstance = "auto"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$configPath = "D:\EPproject\LabelReplaceServer\deployment\config\deployment-config.json"
|
||||
$stateFile = "D:\EPproject\LabelReplaceServer\deployment\instance_state.json"
|
||||
$logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log"
|
||||
|
||||
function Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] [BluGreen] $Message"
|
||||
Write-Host $logEntry -ForegroundColor $(switch($Level) {
|
||||
"ERROR" { "Red" }
|
||||
"WARN" { "Yellow" }
|
||||
"INFO" { "Green" }
|
||||
"DEBUG" { "Gray" }
|
||||
default { "White" }
|
||||
})
|
||||
|
||||
$logDirPath = Split-Path -Parent $logFile
|
||||
if (!(Test-Path $logDirPath)) {
|
||||
New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
|
||||
}
|
||||
Add-Content -Path $logFile -Value $logEntry
|
||||
}
|
||||
|
||||
function GetCurrentActiveInstance {
|
||||
if (Test-Path $stateFile) {
|
||||
try {
|
||||
$state = Get-Content $stateFile | ConvertFrom-Json
|
||||
return $state.activeInstance
|
||||
}
|
||||
catch {
|
||||
Log "读取状态文件失败,假设Blue为活跃实例" "WARN"
|
||||
return "blue"
|
||||
}
|
||||
}
|
||||
return "blue"
|
||||
}
|
||||
|
||||
function SetActiveInstance {
|
||||
param([string]$Instance)
|
||||
|
||||
$state = @{
|
||||
activeInstance = $Instance
|
||||
lastUpdate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
version = $Version
|
||||
}
|
||||
|
||||
$logDirPath = Split-Path -Parent $stateFile
|
||||
if (!(Test-Path $logDirPath)) {
|
||||
New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
|
||||
}
|
||||
|
||||
$state | ConvertTo-Json | Set-Content -Path $stateFile -Force
|
||||
Log "已更新活跃实例为: $Instance (版本: $Version)" "INFO"
|
||||
}
|
||||
|
||||
function StopInstance {
|
||||
param([string]$Instance, [int]$Port)
|
||||
|
||||
Log "尝试停止 $Instance 实例 (端口: $Port)..." "INFO"
|
||||
|
||||
try {
|
||||
$processes = Get-Process | Where-Object {
|
||||
$_.ProcessName -eq "CONTROLLER" -and $_.Handles -gt 0
|
||||
}
|
||||
|
||||
foreach ($proc in $processes) {
|
||||
try {
|
||||
$proc | Stop-Process -Force -ErrorAction Stop
|
||||
Log "已停止进程 $($proc.Id)" "INFO"
|
||||
}
|
||||
catch {
|
||||
Log "停止进程失败: $_" "WARN"
|
||||
}
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
$stillRunning = Get-Process | Where-Object {
|
||||
$_.ProcessName -eq "CONTROLLER"
|
||||
}
|
||||
|
||||
if ($stillRunning) {
|
||||
Log "警告: 仍有 CONTROLLER 进程运行" "WARN"
|
||||
return $false
|
||||
}
|
||||
|
||||
Log "$Instance 实例已成功停止" "INFO"
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Log "停止 $Instance 实例失败: $_" "ERROR"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function StartInstance {
|
||||
param([string]$Instance, [string]$Directory, [string]$Port, [string]$Environment)
|
||||
|
||||
Log "启动 $Instance 实例 (端口: $Port, 目录: $Directory)..." "INFO"
|
||||
|
||||
try {
|
||||
if (!(Test-Path $Directory)) {
|
||||
throw "目录不存在: $Directory"
|
||||
}
|
||||
|
||||
$exePath = Join-Path $Directory "CONTROLLER.exe"
|
||||
if (!(Test-Path $exePath)) {
|
||||
throw "可执行文件不存在: $exePath"
|
||||
}
|
||||
|
||||
$env:DEPLOYMENT_INSTANCE = if ($Instance -eq "green") { "green" } else { "blue" }
|
||||
$env:SHUTDOWN_TIMEOUT = "30"
|
||||
|
||||
$process = Start-Process -FilePath $exePath -WorkingDirectory $Directory -PassThru -ErrorAction Stop
|
||||
|
||||
Log "$Instance 实例已启动 (PID: $($process.Id))" "INFO"
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
return $process.Id
|
||||
}
|
||||
catch {
|
||||
Log "启动 $Instance 实例失败: $_" "ERROR"
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Log "========================================" "INFO"
|
||||
Log "蓝绿部署流程开始" "INFO"
|
||||
Log "版本: $Version" "INFO"
|
||||
Log "========================================" "INFO"
|
||||
|
||||
if (!(Test-Path $configPath)) {
|
||||
throw "配置文件不存在: $configPath"
|
||||
}
|
||||
|
||||
$config = Get-Content $configPath | ConvertFrom-Json
|
||||
Log "已加载部署配置" "INFO"
|
||||
|
||||
$currentActive = GetCurrentActiveInstance
|
||||
Log "当前活跃实例: $currentActive" "INFO"
|
||||
|
||||
$nextInstance = if ($currentActive -eq "blue") { "green" } else { "blue" }
|
||||
|
||||
if ($TargetInstance -ne "auto") {
|
||||
$nextInstance = $TargetInstance
|
||||
Log "使用指定的目标实例: $nextInstance" "INFO"
|
||||
}
|
||||
|
||||
Log "下一个部署实例: $nextInstance" "INFO"
|
||||
|
||||
$targetConfig = if ($nextInstance -eq "green") {
|
||||
$config.GreenInstance
|
||||
} else {
|
||||
$config.BlueInstance
|
||||
}
|
||||
|
||||
Log "========== 第一步:编译和发布 ==========" "INFO"
|
||||
$publishScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\build-and-publish.ps1"
|
||||
$buildResult = & $publishScript -OutputDirectory $targetConfig.Directory -Version $Version -Configuration Release
|
||||
|
||||
if (!$buildResult) {
|
||||
throw "编译和发布失败"
|
||||
}
|
||||
|
||||
Log "========== 第二步:启动新实例 ==========" "INFO"
|
||||
$newPid = StartInstance -Instance $nextInstance -Directory $targetConfig.Directory `
|
||||
-Port $targetConfig.Port -Environment $targetConfig.Environment
|
||||
|
||||
Log "========== 第三步:健康检查 ==========" "INFO"
|
||||
$healthScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\health-check.ps1"
|
||||
$healthResult = & $healthScript -Instance $nextInstance -Port $targetConfig.Port
|
||||
|
||||
if (!$healthResult) {
|
||||
throw "新实例健康检查失败,中止部署"
|
||||
}
|
||||
|
||||
Log "========== 第四步:切换流量 ==========" "INFO"
|
||||
SetActiveInstance -Instance $nextInstance
|
||||
|
||||
Log "========== 第五步:停止旧实例 ==========" "INFO"
|
||||
$oldConfig = if ($currentActive -eq "green") {
|
||||
$config.GreenInstance
|
||||
} else {
|
||||
$config.BlueInstance
|
||||
}
|
||||
|
||||
Log "等待旧实例优雅关闭 (超时: $($config.Deployment.GracefulShutdownTimeout) 秒)..." "INFO"
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
StopInstance -Instance $currentActive -Port $oldConfig.Port
|
||||
|
||||
Log "========================================" "INFO"
|
||||
Log "蓝绿部署完成!" "INFO"
|
||||
Log "新活跃实例: $nextInstance (端口: $($targetConfig.Port))" "INFO"
|
||||
Log "========================================" "INFO"
|
||||
}
|
||||
catch {
|
||||
Log "蓝绿部署失败: $_" "ERROR"
|
||||
Log "错误详情: $($_.Exception.StackTrace)" "ERROR"
|
||||
exit 1
|
||||
}
|
||||
72
deployment/scripts/health-check.ps1
Normal file
72
deployment/scripts/health-check.ps1
Normal file
@@ -0,0 +1,72 @@
|
||||
param(
|
||||
[string]$Instance = "blue",
|
||||
[int]$Port = 5000,
|
||||
[int]$MaxRetries = 30,
|
||||
[int]$RetryDelayMs = 1000,
|
||||
[int]$TimeoutSeconds = 10
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
$logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log"
|
||||
|
||||
function Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] [HealthCheck:$Instance] $Message"
|
||||
Write-Host $logEntry
|
||||
|
||||
$logDirPath = Split-Path -Parent $logFile
|
||||
if (!(Test-Path $logDirPath)) {
|
||||
New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
|
||||
}
|
||||
Add-Content -Path $logFile -Value $logEntry
|
||||
}
|
||||
|
||||
function CheckHealth {
|
||||
param([int]$CurrentAttempt)
|
||||
|
||||
try {
|
||||
$url = "http://localhost:$Port/api/health"
|
||||
$response = Invoke-WebRequest -Uri $url -Method Get -TimeoutSec $TimeoutSeconds -ErrorAction Stop
|
||||
|
||||
if ($response.StatusCode -eq 200) {
|
||||
Log "健康检查成功 (尝试 $CurrentAttempt/$MaxRetries)" "INFO"
|
||||
|
||||
$content = $response.Content | ConvertFrom-Json
|
||||
Log "实例状态: $($content.status), 环境: $($content.environment)" "INFO"
|
||||
|
||||
return $true
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Log "健康检查失败 (尝试 $CurrentAttempt/$MaxRetries): $($_.Exception.Message)" "WARN"
|
||||
}
|
||||
|
||||
return $false
|
||||
}
|
||||
|
||||
try {
|
||||
Log "开始健康检查 - 实例: $Instance, 端口: $Port" "INFO"
|
||||
Log "最大重试次数: $MaxRetries, 重试间隔: ${RetryDelayMs}ms, 超时: ${TimeoutSeconds}s" "INFO"
|
||||
|
||||
for ($i = 1; $i -le $MaxRetries; $i++) {
|
||||
if (CheckHealth -CurrentAttempt $i) {
|
||||
Log "健康检查通过" "INFO"
|
||||
return $true
|
||||
}
|
||||
|
||||
if ($i -lt $MaxRetries) {
|
||||
Log "等待 ${RetryDelayMs}ms 后重试..." "INFO"
|
||||
Start-Sleep -Milliseconds $RetryDelayMs
|
||||
}
|
||||
}
|
||||
|
||||
Log "健康检查失败: 在 $MaxRetries 次重试后仍未响应" "ERROR"
|
||||
return $false
|
||||
}
|
||||
catch {
|
||||
Log "健康检查执行异常: $_" "ERROR"
|
||||
Log "错误详情: $($_.Exception.StackTrace)" "ERROR"
|
||||
return $false
|
||||
}
|
||||
179
deployment/scripts/rollback.ps1
Normal file
179
deployment/scripts/rollback.ps1
Normal file
@@ -0,0 +1,179 @@
|
||||
param(
|
||||
[string]$BackupVersion = $null
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$configPath = "D:\EPproject\LabelReplaceServer\deployment\config\deployment-config.json"
|
||||
$stateFile = "D:\EPproject\LabelReplaceServer\deployment\instance_state.json"
|
||||
$logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log"
|
||||
$backupDir = "D:\EPproject\LabelReplaceServer\deployment\backups"
|
||||
|
||||
function Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] [Rollback] $Message"
|
||||
Write-Host $logEntry -ForegroundColor $(switch($Level) {
|
||||
"ERROR" { "Red" }
|
||||
"WARN" { "Yellow" }
|
||||
"INFO" { "Green" }
|
||||
default { "White" }
|
||||
})
|
||||
|
||||
$logDirPath = Split-Path -Parent $logFile
|
||||
if (!(Test-Path $logDirPath)) {
|
||||
New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
|
||||
}
|
||||
Add-Content -Path $logFile -Value $logEntry
|
||||
}
|
||||
|
||||
function GetLatestBackup {
|
||||
if (!(Test-Path $backupDir)) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$backups = Get-ChildItem -Path $backupDir -Directory | Sort-Object -Property LastWriteTime -Descending
|
||||
return $backups[0]
|
||||
}
|
||||
|
||||
function RestoreFromBackup {
|
||||
param([string]$BackupPath, [string]$TargetPath)
|
||||
|
||||
Log "从备份恢复: $BackupPath -> $TargetPath" "INFO"
|
||||
|
||||
if (Test-Path $TargetPath) {
|
||||
Log "移除现有实例目录..." "INFO"
|
||||
Remove-Item -Path $TargetPath -Recurse -Force
|
||||
}
|
||||
|
||||
Copy-Item -Path $BackupPath -Destination $TargetPath -Recurse -Force
|
||||
Log "已从备份恢复文件" "INFO"
|
||||
}
|
||||
|
||||
function StartInstance {
|
||||
param([string]$Instance, [string]$Directory, [int]$Port)
|
||||
|
||||
Log "启动 $Instance 实例 (端口: $Port)..." "INFO"
|
||||
|
||||
try {
|
||||
$exePath = Join-Path $Directory "CONTROLLER.exe"
|
||||
|
||||
$env:DEPLOYMENT_INSTANCE = if ($Instance -eq "green") { "green" } else { "blue" }
|
||||
$env:SHUTDOWN_TIMEOUT = "30"
|
||||
|
||||
$process = Start-Process -FilePath $exePath -WorkingDirectory $Directory -PassThru
|
||||
|
||||
Log "$Instance 实例已启动 (PID: $($process.Id))" "INFO"
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
return $process.Id
|
||||
}
|
||||
catch {
|
||||
Log "启动实例失败: $_" "ERROR"
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
function StopInstance {
|
||||
param([int]$GracefulTimeout = 30)
|
||||
|
||||
try {
|
||||
$controller = Get-Process -Name CONTROLLER -ErrorAction SilentlyContinue
|
||||
|
||||
if ($null -eq $controller) {
|
||||
Log "CONTROLLER 进程未找到" "WARN"
|
||||
return $true
|
||||
}
|
||||
|
||||
Log "停止 CONTROLLER 进程 (PID: $($controller.Id))..." "INFO"
|
||||
|
||||
if ($controller.WaitForExit($GracefulTimeout * 1000)) {
|
||||
Log "进程已退出" "INFO"
|
||||
return $true
|
||||
}
|
||||
|
||||
Log "强制终止进程..." "WARN"
|
||||
$controller | Stop-Process -Force
|
||||
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Log "停止实例失败: $_" "ERROR"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Log "========================================" "INFO"
|
||||
Log "开始回滚流程" "INFO"
|
||||
Log "========================================" "INFO"
|
||||
|
||||
if (!(Test-Path $configPath)) {
|
||||
throw "配置文件不存在: $configPath"
|
||||
}
|
||||
|
||||
$config = Get-Content $configPath | ConvertFrom-Json
|
||||
|
||||
if (!(Test-Path $stateFile)) {
|
||||
throw "状态文件不存在: $stateFile,无法确定当前实例"
|
||||
}
|
||||
|
||||
$state = Get-Content $stateFile | ConvertFrom-Json
|
||||
$currentInstance = $state.activeInstance
|
||||
$previousInstance = if ($currentInstance -eq "blue") { "green" } else { "blue" }
|
||||
|
||||
Log "当前活跃实例: $currentInstance" "INFO"
|
||||
Log "回滚目标实例: $previousInstance" "INFO"
|
||||
|
||||
$backup = GetLatestBackup
|
||||
if ($null -eq $backup) {
|
||||
throw "没有找到备份文件"
|
||||
}
|
||||
|
||||
Log "最新备份: $($backup.Name)" "INFO"
|
||||
|
||||
$previousConfig = if ($previousInstance -eq "green") {
|
||||
$config.GreenInstance
|
||||
}
|
||||
else {
|
||||
$config.BlueInstance
|
||||
}
|
||||
|
||||
Log "========== 第一步:停止当前实例 ==========" "INFO"
|
||||
StopInstance -GracefulTimeout 30
|
||||
|
||||
Log "========== 第二步:恢复备份 ==========" "INFO"
|
||||
RestoreFromBackup -BackupPath $backup.FullName -TargetPath $previousConfig.Directory
|
||||
|
||||
Log "========== 第三步:启动恢复的实例 ==========" "INFO"
|
||||
$pid = StartInstance -Instance $previousInstance -Directory $previousConfig.Directory `
|
||||
-Port $previousConfig.Port
|
||||
|
||||
Log "========== 第四步:健康检查 ==========" "INFO"
|
||||
$healthScript = "D:\EPproject\LabelReplaceServer\deployment\scripts\health-check.ps1"
|
||||
$healthResult = & $healthScript -Instance $previousInstance -Port $previousConfig.Port
|
||||
|
||||
if (!$healthResult) {
|
||||
throw "恢复的实例健康检查失败"
|
||||
}
|
||||
|
||||
Log "========== 第五步:更新活跃实例 ==========" "INFO"
|
||||
$newState = @{
|
||||
activeInstance = $previousInstance
|
||||
lastUpdate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
version = $state.version
|
||||
rolledBack = $true
|
||||
}
|
||||
|
||||
$newState | ConvertTo-Json | Set-Content -Path $stateFile -Force
|
||||
|
||||
Log "========================================" "INFO"
|
||||
Log "回滚完成!" "INFO"
|
||||
Log "新活跃实例: $previousInstance (端口: $($previousConfig.Port))" "INFO"
|
||||
Log "========================================" "INFO"
|
||||
}
|
||||
catch {
|
||||
Log "回滚失败: $_" "ERROR"
|
||||
Log "错误详情: $($_.Exception.StackTrace)" "ERROR"
|
||||
exit 1
|
||||
}
|
||||
60
deployment/scripts/stop-instance.ps1
Normal file
60
deployment/scripts/stop-instance.ps1
Normal file
@@ -0,0 +1,60 @@
|
||||
param(
|
||||
[string]$Instance = "blue",
|
||||
[int]$Port = 5000,
|
||||
[int]$GracefulTimeoutSeconds = 30
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
$logFile = "D:\EPproject\LabelReplaceServer\deployment\logs\deployment.log"
|
||||
|
||||
function Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logEntry = "[$timestamp] [$Level] [StopInstance:$Instance] $Message"
|
||||
Write-Host $logEntry
|
||||
|
||||
$logDirPath = Split-Path -Parent $logFile
|
||||
if (!(Test-Path $logDirPath)) {
|
||||
New-Item -ItemType Directory -Path $logDirPath -Force | Out-Null
|
||||
}
|
||||
Add-Content -Path $logFile -Value $logEntry
|
||||
}
|
||||
|
||||
try {
|
||||
Log "========== 优雅关闭实例 ==========" "INFO"
|
||||
Log "实例: $Instance, 端口: $Port" "INFO"
|
||||
Log "优雅超时: $GracefulTimeoutSeconds 秒" "INFO"
|
||||
|
||||
$controller = Get-Process -Name CONTROLLER -ErrorAction SilentlyContinue
|
||||
|
||||
if ($null -eq $controller) {
|
||||
Log "CONTROLLER 进程未找到" "WARN"
|
||||
return $true
|
||||
}
|
||||
|
||||
Log "找到 CONTROLLER 进程 (PID: $($controller.Id))" "INFO"
|
||||
Log "等待进程优雅退出..." "INFO"
|
||||
|
||||
if ($controller.WaitForExit($GracefulTimeoutSeconds * 1000)) {
|
||||
Log "进程已优雅退出" "INFO"
|
||||
return $true
|
||||
}
|
||||
|
||||
Log "进程未在 $GracefulTimeoutSeconds 秒内退出,强制终止..." "WARN"
|
||||
|
||||
try {
|
||||
$controller | Stop-Process -Force -ErrorAction Stop
|
||||
Log "进程已强制终止" "INFO"
|
||||
}
|
||||
catch {
|
||||
Log "强制终止失败: $_" "ERROR"
|
||||
return $false
|
||||
}
|
||||
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
Log "优雅关闭异常: $_" "ERROR"
|
||||
return $false
|
||||
}
|
||||
Reference in New Issue
Block a user