# dev/stop.ps1 — 停掉本地开发环境 # # 先按 .run\ 里登记的 PID 停(连子进程一起杀), # 再检查端口上是否还残留「本脚本管不到」的进程,报告但不强杀(除非 -Force)。 param( [switch]$Force ) $ErrorActionPreference = 'Stop' $CliRoot = Split-Path -Parent $PSScriptRoot . (Join-Path $CliRoot 'lib\common.ps1') $envMap = Import-LocalEnv (Join-Path $CliRoot 'config\local.env') $backendPort = [int](Get-Setting $envMap 'BACKEND_PORT' '8090') $frontendPort = [int](Get-Setting $envMap 'FRONTEND_PORT' '4321') $visionPort = [int](Get-Setting $envMap 'VISION_PORT' '8900') Write-Host '' Write-Host ' 停止本地开发环境' -ForegroundColor White Write-Host ' ----------------------------------------' -ForegroundColor DarkGray $services = @( @{ Name = 'frontend'; Port = $frontendPort }, @{ Name = 'backend'; Port = $backendPort }, @{ Name = 'vision'; Port = $visionPort } ) foreach ($s in $services) { if (Stop-NamedService $s.Name) { Write-Ok "$($s.Name) 已停止" } else { Write-Note "$($s.Name) 未在本脚本登记(可能没启动过)" } } # 后端占了三个端口,只停 8090 后 8091/8092 会随进程一起消失,这里只做残留检查 Write-Host '' $leftover = @() foreach ($port in @($backendPort, 8091, 8092, $frontendPort, $visionPort)) { if (-not (Test-PortInUse $port)) { continue } $owner = Get-PortOwnerPid $port $leftover += [PSCustomObject]@{ Port = $port; Pid = $owner } } if ($leftover.Count -eq 0) { Write-Ok '相关端口已全部释放' exit 0 } foreach ($l in $leftover) { Write-Warn ("端口 " + $l.Port + " 仍被 PID " + $l.Pid + " 占用") } if ($Force) { foreach ($id in ($leftover | Select-Object -ExpandProperty Pid | Sort-Object -Unique)) { Stop-PidTree $id | Out-Null Write-Ok "已终止 PID $id" } Write-Host '' foreach ($port in @($backendPort, 8091, 8092, $frontendPort, $visionPort)) { if (Test-PortInUse $port) { Write-Warn "端口 $port 仍被占用" } } } else { Write-Note '这些进程不是本脚本启动的(例如手动 go run / npm run dev 留下的)。' Write-Note '需要一起停掉就加 -Force:.\dev\stop.ps1 -Force' }