mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 09:23:17 +08:00
Fix empty Cisco IOSv CLI output and harden Windows stop/start.
Drain leftover prompts before Netmiko send_command, and make stop/start tolerate orphan workers and locked log files. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
3612dd6e45
commit
bd01440e9d
5 changed files with 187 additions and 49 deletions
|
|
@ -131,25 +131,38 @@ function Test-NetxApiListening {
|
|||
return $false
|
||||
}
|
||||
|
||||
function Reset-LogFile {
|
||||
param([string]$Path)
|
||||
try {
|
||||
Set-Content -Path $Path -Value "" -Encoding utf8 -ErrorAction Stop
|
||||
return $Path
|
||||
} catch {
|
||||
$alt = "$Path.$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
||||
Write-Host "[WARN] cannot truncate $Path ($($_.Exception.Message))" -ForegroundColor Yellow
|
||||
Write-Host " using $alt (old worker may still hold the previous file; run stop_netx.ps1 elevated)" -ForegroundColor Yellow
|
||||
return $alt
|
||||
}
|
||||
}
|
||||
|
||||
function Start-NetxWorker {
|
||||
if ($InlineSchedulers) {
|
||||
return
|
||||
}
|
||||
Set-Content -Path $workerLogFile -Value "" -Encoding utf8
|
||||
Set-Content -Path $workerErrFile -Value "" -Encoding utf8
|
||||
$outLog = Reset-LogFile -Path $workerLogFile
|
||||
$errLog = Reset-LogFile -Path $workerErrFile
|
||||
Write-Host "==> Starting netx worker (config_sync / lldp / port_traffic)"
|
||||
$workerProc = Start-Process -FilePath $pythonExe `
|
||||
-ArgumentList @("-m", "netx_api.worker") `
|
||||
-WorkingDirectory $projectRoot `
|
||||
-WindowStyle Hidden `
|
||||
-RedirectStandardOutput $workerLogFile `
|
||||
-RedirectStandardError $workerErrFile `
|
||||
-RedirectStandardOutput $outLog `
|
||||
-RedirectStandardError $errLog `
|
||||
-PassThru
|
||||
Set-Content -Path $workerPidFile -Value "$($workerProc.Id)"
|
||||
Write-Host "worker.pid = $workerPidFile"
|
||||
Write-Host "PID = $($workerProc.Id)"
|
||||
Write-Host "Log = $workerLogFile"
|
||||
Write-Host "Err = $workerErrFile"
|
||||
Write-Host "Log = $outLog"
|
||||
Write-Host "Err = $errLog"
|
||||
Start-Sleep -Seconds 1
|
||||
$alive = $false
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,35 @@
|
|||
param(
|
||||
[int]$Port = 8890,
|
||||
[int]$WebPort = 5173,
|
||||
[switch]$Force = $false
|
||||
# Windows often ignores graceful Stop-Process on python; default hard-kill.
|
||||
[switch]$Force = $true,
|
||||
[switch]$NoForce = $false
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$useForce = if ($NoForce) { $false } else { [bool]$Force }
|
||||
|
||||
$runDir = Join-Path $PSScriptRoot ".run"
|
||||
$pidFile = Join-Path $runDir "netx.pid"
|
||||
$workerPidFile = Join-Path $runDir "worker.pid"
|
||||
$webPidFile = Join-Path $runDir "web.pid"
|
||||
|
||||
function Stop-OnePid {
|
||||
param([int]$ProcId, [string]$Label)
|
||||
if ($ProcId -le 4) { return }
|
||||
if ($ProcId -eq $PID) { return }
|
||||
try {
|
||||
Stop-Process -Id $ProcId -Force:$useForce -ErrorAction Stop
|
||||
Write-Host "Stopped $Label PID=$ProcId"
|
||||
} catch {
|
||||
$msg = $_.Exception.Message
|
||||
Write-Host "[WARN] Failed to stop $Label PID=$ProcId : $msg"
|
||||
if ($msg -match 'Access|Denied|拒绝|拒绝访问') {
|
||||
Write-Host " Run elevated PowerShell, then: taskkill /F /PID $ProcId" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ListenPids {
|
||||
param([int]$LocalPort)
|
||||
$ids = [System.Collections.Generic.HashSet[int]]::new()
|
||||
|
|
@ -40,19 +59,28 @@ function Get-ListenPids {
|
|||
@($ids)
|
||||
}
|
||||
|
||||
Write-Host "==> Stopping netx"
|
||||
function Stop-NetxByCommandLine {
|
||||
# Orphan workers often have no worker.pid but still hold worker.out.log.
|
||||
$hits = @(Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.CommandLine -match 'netx_api\.(main|worker)' })
|
||||
if ($hits.Count -eq 0) {
|
||||
Write-Host "[INFO] No netx_api.main/worker process by command line"
|
||||
return
|
||||
}
|
||||
foreach ($p in $hits) {
|
||||
$kind = if ($p.CommandLine -match 'netx_api\.worker') { "worker(cmd)" } else { "api(cmd)" }
|
||||
Stop-OnePid -ProcId ([int]$p.ProcessId) -Label $kind
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "==> Stopping netx (Force=$useForce)"
|
||||
|
||||
if (Test-Path $pidFile) {
|
||||
$pidText = (Get-Content -Path $pidFile -ErrorAction SilentlyContinue | Select-Object -First 1)
|
||||
$procId = 0
|
||||
[void][int]::TryParse("$pidText", [ref]$procId)
|
||||
if ($procId -gt 0) {
|
||||
try {
|
||||
Stop-Process -Id $procId -Force:$Force -ErrorAction Stop
|
||||
Write-Host "Stopped API PID=$procId"
|
||||
} catch {
|
||||
Write-Host "[WARN] PID file process not running: $procId"
|
||||
}
|
||||
Stop-OnePid -ProcId $procId -Label "API"
|
||||
}
|
||||
Remove-Item -Path $pidFile -Force -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
|
|
@ -64,12 +92,7 @@ if (Test-Path $workerPidFile) {
|
|||
$workerProcId = 0
|
||||
[void][int]::TryParse("$workerPidText", [ref]$workerProcId)
|
||||
if ($workerProcId -gt 0) {
|
||||
try {
|
||||
Stop-Process -Id $workerProcId -Force:$Force -ErrorAction Stop
|
||||
Write-Host "Stopped worker PID=$workerProcId"
|
||||
} catch {
|
||||
Write-Host "[WARN] worker PID file process not running: $workerProcId"
|
||||
}
|
||||
Stop-OnePid -ProcId $workerProcId -Label "worker"
|
||||
}
|
||||
Remove-Item -Path $workerPidFile -Force -ErrorAction SilentlyContinue
|
||||
} else {
|
||||
|
|
@ -81,26 +104,17 @@ if (Test-Path $webPidFile) {
|
|||
$webProcId = 0
|
||||
[void][int]::TryParse("$webPidText", [ref]$webProcId)
|
||||
if ($webProcId -gt 0) {
|
||||
try {
|
||||
Stop-Process -Id $webProcId -Force:$Force -ErrorAction Stop
|
||||
Write-Host "Stopped web PID=$webProcId"
|
||||
} catch {
|
||||
Write-Host "[WARN] web PID file process not running: $webProcId"
|
||||
}
|
||||
Stop-OnePid -ProcId $webProcId -Label "web"
|
||||
}
|
||||
Remove-Item -Path $webPidFile -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Stop-NetxByCommandLine
|
||||
|
||||
$owningApi = @(Get-ListenPids -LocalPort $Port)
|
||||
if ($owningApi.Count -gt 0) {
|
||||
foreach ($procId in $owningApi) {
|
||||
if ($procId -eq $PID) { continue }
|
||||
try {
|
||||
Stop-Process -Id $procId -Force:$Force -ErrorAction Stop
|
||||
Write-Host "Stopped by port PID=$procId"
|
||||
} catch {
|
||||
Write-Host "[WARN] Failed to stop PID=$procId by port"
|
||||
}
|
||||
Stop-OnePid -ProcId $procId -Label "port:$Port"
|
||||
}
|
||||
} else {
|
||||
Write-Host "[INFO] No listener found on port $Port"
|
||||
|
|
@ -109,13 +123,7 @@ if ($owningApi.Count -gt 0) {
|
|||
$owningWeb = @(Get-ListenPids -LocalPort $WebPort)
|
||||
if ($owningWeb.Count -gt 0) {
|
||||
foreach ($procId in $owningWeb) {
|
||||
if ($procId -eq $PID) { continue }
|
||||
try {
|
||||
Stop-Process -Id $procId -Force:$Force -ErrorAction Stop
|
||||
Write-Host "Stopped web by port PID=$procId"
|
||||
} catch {
|
||||
Write-Host "[WARN] Failed to stop web PID=$procId by port"
|
||||
}
|
||||
Stop-OnePid -ProcId $procId -Label "port:$WebPort"
|
||||
}
|
||||
} else {
|
||||
Write-Host "[INFO] No listener found on web port $WebPort"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue