chore: initialize insar management system v2
This commit is contained in:
@@ -0,0 +1,594 @@
|
||||
# InSAR Management System - Startup Script (PowerShell)
|
||||
# Features:
|
||||
# - Process management (stop old instances, start new ones)
|
||||
# - Database health check
|
||||
# - Auto Nginx config update
|
||||
# - Logs output
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# 1. Set project root
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||
$ProjectRoot = Split-Path -Parent $ScriptDir
|
||||
Set-Location -LiteralPath "$ProjectRoot"
|
||||
|
||||
Write-Host ">>> Starting InSAR Management System V2..." -ForegroundColor Cyan
|
||||
Write-Host ">>> Project Root: $ProjectRoot"
|
||||
|
||||
# 2. Parse .env minimally (only for resolving Python/Conda before handing off to unified config)
|
||||
$EnvPath = Join-Path $ProjectRoot ".env"
|
||||
if (-not (Test-Path -LiteralPath "$EnvPath")) {
|
||||
Write-Error "File .env not found: $EnvPath"
|
||||
return
|
||||
}
|
||||
|
||||
$PythonExe = "python"
|
||||
$CondaExe = ""
|
||||
$CondaEnvName = ""
|
||||
$NginxExe = "C:/nginx-1.29.4/nginx.exe"
|
||||
$ServerHost = ""
|
||||
$ServerPort = 18000
|
||||
|
||||
$envLines = Get-Content -LiteralPath "$EnvPath"
|
||||
foreach ($line in $envLines) {
|
||||
$trimmed = $line.Trim()
|
||||
if ($trimmed.StartsWith("#") -or -not $trimmed.Contains("=")) { continue }
|
||||
|
||||
$parts = $trimmed.Split("=", 2)
|
||||
$key = $parts[0].Trim()
|
||||
$val = $parts[1].Trim().Trim('"').Trim("'")
|
||||
|
||||
if ($key -eq "PYTHON_PATH") { if ($val) { $PythonExe = $val } }
|
||||
if ($key -eq "CONDA_EXE") { if ($val) { $CondaExe = $val } }
|
||||
if ($key -eq "CONDA_ENV_NAME") { if ($val) { $CondaEnvName = $val } }
|
||||
if ($key -eq "NGINX_PATH") { if ($val) { $NginxExe = $val } }
|
||||
if ($key -eq "BACKEND_BIND_HOST") { if ($val) { $ServerHost = $val } }
|
||||
if ($key -eq "PORT") {
|
||||
$parsed = 0
|
||||
if ([int]::TryParse($val, [ref]$parsed)) { $ServerPort = $parsed }
|
||||
}
|
||||
}
|
||||
|
||||
$CheckDbScript = Join-Path $ProjectRoot "scripts\check_db_connection.py"
|
||||
$CheckRuntimeScript = Join-Path $ProjectRoot "scripts\check_runtime_config.py"
|
||||
$ExportLauncherConfigScript = Join-Path $ProjectRoot "scripts\export_launcher_config.py"
|
||||
$InitDbScript = Join-Path $ProjectRoot "scripts\init_db.py"
|
||||
|
||||
function Resolve-ExecutablePath {
|
||||
param([string]$Candidate)
|
||||
|
||||
$trimmed = "$Candidate".Trim().Trim('"').Trim("'")
|
||||
if (-not $trimmed) {
|
||||
return $null
|
||||
}
|
||||
|
||||
if (Test-Path -LiteralPath "$trimmed") {
|
||||
$resolved = Resolve-Path -LiteralPath "$trimmed" -ErrorAction SilentlyContinue
|
||||
if ($resolved) {
|
||||
return $resolved.Path
|
||||
}
|
||||
return $trimmed
|
||||
}
|
||||
|
||||
$cmd = Get-Command -Name "$trimmed" -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if ($cmd -and $cmd.Source) {
|
||||
return $cmd.Source
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Resolve-CondaEnvPythonPath {
|
||||
param(
|
||||
[string]$ResolvedCondaExe,
|
||||
[string]$EnvName
|
||||
)
|
||||
|
||||
$trimmedEnvName = "$EnvName".Trim()
|
||||
if (-not $trimmedEnvName) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$anacondaRoot = Split-Path -Parent (Split-Path -Parent "$ResolvedCondaExe")
|
||||
$candidatePaths = @(
|
||||
(Join-Path -Path $anacondaRoot -ChildPath "envs\$trimmedEnvName\python.exe"),
|
||||
(Join-Path -Path $env:USERPROFILE -ChildPath ".conda\envs\$trimmedEnvName\python.exe")
|
||||
)
|
||||
|
||||
foreach ($candidate in $candidatePaths) {
|
||||
if (Test-Path -LiteralPath "$candidate") {
|
||||
$resolved = Resolve-Path -LiteralPath "$candidate" -ErrorAction SilentlyContinue
|
||||
if ($resolved) {
|
||||
return $resolved.Path
|
||||
}
|
||||
return $candidate
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$envsJson = & "$ResolvedCondaExe" info --envs --json 2>$null
|
||||
if ($LASTEXITCODE -eq 0 -and $envsJson) {
|
||||
$envsInfo = $envsJson | ConvertFrom-Json
|
||||
foreach ($envPath in ($envsInfo.envs | Where-Object { $_ })) {
|
||||
if ((Split-Path -Leaf "$envPath") -ne $trimmedEnvName) {
|
||||
continue
|
||||
}
|
||||
$pythonPath = Join-Path -Path "$envPath" -ChildPath "python.exe"
|
||||
if (Test-Path -LiteralPath "$pythonPath") {
|
||||
$resolved = Resolve-Path -LiteralPath "$pythonPath" -ErrorAction SilentlyContinue
|
||||
if ($resolved) {
|
||||
return $resolved.Path
|
||||
}
|
||||
return $pythonPath
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
# Ignore and continue with fallback.
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Invoke-PythonScript {
|
||||
param([string]$ScriptPath)
|
||||
|
||||
& "$PythonExe" "$ScriptPath"
|
||||
}
|
||||
|
||||
function Invoke-PythonScriptJson {
|
||||
param([string]$ScriptPath)
|
||||
|
||||
$output = & "$PythonExe" "$ScriptPath"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
return $null
|
||||
}
|
||||
if (-not $output) {
|
||||
return $null
|
||||
}
|
||||
return ($output | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
# 3. Stop old instances
|
||||
Write-Host ">>> Stopping existing processes..." -ForegroundColor Yellow
|
||||
|
||||
function Stop-Process-By-Name {
|
||||
param([string]$Name, [string]$ExeName)
|
||||
# Prefer precise cmdline matching; fall back to executable path when CIM command line is unavailable.
|
||||
$NginxConfMatch = Join-Path -Path $ProjectRoot -ChildPath "nginx"
|
||||
$matched = @()
|
||||
$resolvedExe = Resolve-ExecutablePath -Candidate $ExeName
|
||||
|
||||
$candidates = Get-CimInstance Win32_Process -Filter "Name='$Name.exe'" -ErrorAction SilentlyContinue
|
||||
if ($candidates) {
|
||||
foreach ($proc in $candidates) {
|
||||
if ($proc.CommandLine -and $proc.CommandLine -like "*$NginxConfMatch*") {
|
||||
$matched += $proc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($matched.Count -eq 0 -and $resolvedExe) {
|
||||
$processesByPath = Get-Process -Name $Name -ErrorAction SilentlyContinue
|
||||
foreach ($proc in $processesByPath) {
|
||||
$procPath = $null
|
||||
try {
|
||||
$procPath = $proc.Path
|
||||
} catch {
|
||||
$procPath = $null
|
||||
}
|
||||
|
||||
if ($procPath -and ([string]::Equals($procPath, $resolvedExe, [System.StringComparison]::OrdinalIgnoreCase))) {
|
||||
$matched += $proc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($matched.Count -gt 0) {
|
||||
$targetPids = @($matched | ForEach-Object {
|
||||
if ($_.PSObject.Properties['ProcessId']) { $_.ProcessId }
|
||||
elseif ($_.PSObject.Properties['Id']) { $_.Id }
|
||||
} | Where-Object { $_ } | Sort-Object -Unique)
|
||||
|
||||
Write-Host " Stopping $Name (PID: $($targetPids -join ', '))..." -NoNewline
|
||||
foreach ($p in $matched) {
|
||||
$processId = $null
|
||||
if ($p.PSObject.Properties['ProcessId']) { $processId = $p.ProcessId }
|
||||
elseif ($p.PSObject.Properties['Id']) { $processId = $p.Id }
|
||||
if ($processId) {
|
||||
Stop-Process -Id $processId -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
Start-Sleep -Seconds 1
|
||||
$stillAlive = $false
|
||||
foreach ($targetProcessId in $targetPids) {
|
||||
if (Get-Process -Id $targetProcessId -ErrorAction SilentlyContinue) {
|
||||
$stillAlive = $true
|
||||
}
|
||||
}
|
||||
if (-not $stillAlive) {
|
||||
Write-Host " [Done]" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " [Failed]" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-Backend-By-Cmdline {
|
||||
param([string]$MatchText)
|
||||
$candidates = Get-CimInstance Win32_Process -Filter "Name='python.exe'" -ErrorAction SilentlyContinue
|
||||
foreach ($proc in $candidates) {
|
||||
if ($proc.CommandLine -and $proc.CommandLine -like "*$MatchText*") {
|
||||
try {
|
||||
Write-Host " Stopping python (PID $($proc.ProcessId)) with cmdline match: $MatchText" -NoNewline
|
||||
Stop-Process -Id $proc.ProcessId -Force -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 1
|
||||
$check = Get-Process -Id $proc.ProcessId -ErrorAction SilentlyContinue
|
||||
if (-not $check) {
|
||||
Write-Host " [Done]" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " [Failed]" -ForegroundColor Red
|
||||
}
|
||||
} catch {
|
||||
Write-Host " [Failed]" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ListeningPortOwner {
|
||||
param([int]$Port)
|
||||
|
||||
$conn = Get-NetTCPConnection -LocalPort $Port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if ($conn) {
|
||||
$procName = "Unknown"
|
||||
$proc = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
|
||||
if ($proc) {
|
||||
$procName = $proc.ProcessName
|
||||
}
|
||||
|
||||
return [PSCustomObject]@{
|
||||
Port = $Port
|
||||
PID = $conn.OwningProcess
|
||||
ProcessName = $procName
|
||||
LocalAddress = $conn.LocalAddress
|
||||
}
|
||||
}
|
||||
|
||||
$netstatLines = netstat -ano -p tcp 2>$null
|
||||
if ($netstatLines) {
|
||||
foreach ($line in $netstatLines) {
|
||||
$trimmed = "$line".Trim()
|
||||
if (-not $trimmed.StartsWith("TCP")) {
|
||||
continue
|
||||
}
|
||||
if ($trimmed -notmatch "\s+LISTENING\s+") {
|
||||
continue
|
||||
}
|
||||
$parts = $trimmed -split "\s+"
|
||||
if ($parts.Count -lt 5) {
|
||||
continue
|
||||
}
|
||||
$localEndpoint = $parts[1]
|
||||
$pidText = $parts[4]
|
||||
$localPort = -1
|
||||
if ($localEndpoint -match ":(\d+)$") {
|
||||
$localPort = [int]$matches[1]
|
||||
}
|
||||
if ($localPort -ne $Port) {
|
||||
continue
|
||||
}
|
||||
|
||||
$ownerPid = 0
|
||||
[void][int]::TryParse("$pidText", [ref]$ownerPid)
|
||||
$procName = "Unknown"
|
||||
if ($ownerPid -gt 0) {
|
||||
$proc = Get-Process -Id $ownerPid -ErrorAction SilentlyContinue
|
||||
if ($proc) {
|
||||
$procName = $proc.ProcessName
|
||||
}
|
||||
}
|
||||
|
||||
return [PSCustomObject]@{
|
||||
Port = $Port
|
||||
PID = $ownerPid
|
||||
ProcessName = $procName
|
||||
LocalAddress = $localEndpoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Test-PortAvailable {
|
||||
param([int]$Port)
|
||||
|
||||
try {
|
||||
$probe = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, $Port)
|
||||
$probe.Start()
|
||||
$probe.Stop()
|
||||
return $true
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
Stop-Backend-By-Cmdline -MatchText "run_backend.py"
|
||||
Stop-Backend-By-Cmdline -MatchText "run_worker.py"
|
||||
$NginxProcName = Split-Path -Leaf $NginxExe
|
||||
$NginxProcName = $NginxProcName -replace '\.exe$', ''
|
||||
Stop-Process-By-Name -Name $NginxProcName -ExeName $NginxExe
|
||||
|
||||
$PortAvailable = Test-PortAvailable -Port $ServerPort
|
||||
if (-not $PortAvailable) {
|
||||
$PortOwner = Get-ListeningPortOwner -Port $ServerPort
|
||||
if ($PortOwner) {
|
||||
Write-Error (
|
||||
"Backend port $ServerPort is already in use by PID $($PortOwner.PID) " +
|
||||
"($($PortOwner.ProcessName)) on $($PortOwner.LocalAddress). " +
|
||||
"Please stop that process or change PORT in .env."
|
||||
)
|
||||
} else {
|
||||
Write-Error (
|
||||
"Backend port $ServerPort is not available (bind failed). " +
|
||||
"Please stop the process using this port or change PORT in .env."
|
||||
)
|
||||
}
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
|
||||
# 4. Runtime config + database pre-flight check
|
||||
Write-Host ">>> Checking deployment configuration..." -ForegroundColor Yellow
|
||||
|
||||
$UseCondaRun = -not [string]::IsNullOrWhiteSpace("$CondaEnvName".Trim())
|
||||
$ResolvedCondaExe = $null
|
||||
$CondaEnvPythonExe = $null
|
||||
|
||||
if ($UseCondaRun) {
|
||||
if ([string]::IsNullOrWhiteSpace("$CondaExe".Trim())) {
|
||||
$CondaExe = "conda"
|
||||
}
|
||||
$ResolvedCondaExe = Resolve-ExecutablePath -Candidate $CondaExe
|
||||
if (-not $ResolvedCondaExe) {
|
||||
Write-Error "Conda executable not found. CONDA_EXE=$CondaExe"
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
$CondaEnvPythonExe = Resolve-CondaEnvPythonPath -ResolvedCondaExe "$ResolvedCondaExe" -EnvName "$CondaEnvName"
|
||||
if (-not $CondaEnvPythonExe) {
|
||||
Write-Error "Conda environment python not found. CONDA_ENV_NAME=$CondaEnvName"
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
$PythonExe = $CondaEnvPythonExe
|
||||
} else {
|
||||
$ResolvedPythonExe = Resolve-ExecutablePath -Candidate $PythonExe
|
||||
if (-not $ResolvedPythonExe) {
|
||||
Write-Error "Python executable not found. PYTHON_PATH=$PythonExe"
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
$PythonExe = $ResolvedPythonExe
|
||||
}
|
||||
|
||||
$LauncherConfig = Invoke-PythonScriptJson -ScriptPath "$ExportLauncherConfigScript"
|
||||
if (-not $LauncherConfig) {
|
||||
Write-Error "Failed to load launcher runtime configuration from Python settings layer."
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
|
||||
if ($LauncherConfig.nginx_path) {
|
||||
$NginxExe = [string]$LauncherConfig.nginx_path
|
||||
}
|
||||
if ($LauncherConfig.backend_bind_host) {
|
||||
$ServerHost = [string]$LauncherConfig.backend_bind_host
|
||||
}
|
||||
if ($LauncherConfig.port) {
|
||||
$ServerPort = [int]$LauncherConfig.port
|
||||
}
|
||||
|
||||
function Write-StatusLine {
|
||||
param(
|
||||
[string]$Message,
|
||||
[ConsoleColor]$ForegroundColor = [ConsoleColor]::White
|
||||
)
|
||||
|
||||
Write-Host $Message -ForegroundColor $ForegroundColor
|
||||
}
|
||||
|
||||
function Get-BackgroundProcessLogs {
|
||||
param([string]$ScriptPath)
|
||||
|
||||
$LogDir = Join-Path $ProjectRoot "logs"
|
||||
if (-not (Test-Path -LiteralPath "$LogDir")) {
|
||||
New-Item -ItemType Directory -Path "$LogDir" -Force | Out-Null
|
||||
}
|
||||
|
||||
$ScriptBase = [System.IO.Path]::GetFileNameWithoutExtension("$ScriptPath")
|
||||
return [PSCustomObject]@{
|
||||
StdOut = Join-Path $LogDir "$ScriptBase.stdout.log"
|
||||
StdErr = Join-Path $LogDir "$ScriptBase.stderr.log"
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PythonBackground {
|
||||
param([string]$ScriptPath)
|
||||
|
||||
$LogTargets = Get-BackgroundProcessLogs -ScriptPath "$ScriptPath"
|
||||
Write-Host " stdout -> $($LogTargets.StdOut)"
|
||||
Write-Host " stderr -> $($LogTargets.StdErr)"
|
||||
|
||||
return Start-Process `
|
||||
-FilePath "$PythonExe" `
|
||||
-ArgumentList @("$ScriptPath") `
|
||||
-WorkingDirectory "$ProjectRoot" `
|
||||
-PassThru `
|
||||
-NoNewWindow `
|
||||
-RedirectStandardOutput "$($LogTargets.StdOut)" `
|
||||
-RedirectStandardError "$($LogTargets.StdErr)"
|
||||
}
|
||||
|
||||
function Assert-ProcessAlive {
|
||||
param(
|
||||
[System.Diagnostics.Process]$Process,
|
||||
[string]$DisplayName
|
||||
)
|
||||
|
||||
if (-not $Process) {
|
||||
Write-Error "$DisplayName failed to start: process handle is null."
|
||||
$global:LASTEXITCODE = 1
|
||||
return $false
|
||||
}
|
||||
|
||||
Start-Sleep -Milliseconds 800
|
||||
$procCheck = Get-Process -Id $Process.Id -ErrorAction SilentlyContinue
|
||||
if (-not $procCheck) {
|
||||
Write-Error "$DisplayName exited immediately after startup. Please check logs for details."
|
||||
$global:LASTEXITCODE = 1
|
||||
return $false
|
||||
}
|
||||
|
||||
return $true
|
||||
}
|
||||
|
||||
Invoke-PythonScript -ScriptPath "$CheckRuntimeScript"
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Host "`n[ERROR] Deployment configuration check failed." -ForegroundColor Red
|
||||
Write-Host "Please review the error messages above and fix the configuration." -ForegroundColor Red
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host ">>> Checking database connection..." -ForegroundColor Yellow
|
||||
Invoke-PythonScript -ScriptPath "$CheckDbScript"
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Host "`n[ERROR] Database connection check failed." -ForegroundColor Red
|
||||
Write-Host "Please review the error messages above and fix the configuration." -ForegroundColor Red
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
|
||||
# 4.5 Schema sync
|
||||
Write-Host ">>> Checking database schema..." -ForegroundColor Yellow
|
||||
Invoke-PythonScript -ScriptPath "$InitDbScript"
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Host "`n[ERROR] Database schema check failed." -ForegroundColor Red
|
||||
Write-Host "Please review the error messages above and fix the configuration." -ForegroundColor Red
|
||||
$global:LASTEXITCODE = 1
|
||||
return
|
||||
}
|
||||
|
||||
# 5. Update Nginx config (absolute path fix)
|
||||
$NginxConfPath = Join-Path -Path $ProjectRoot -ChildPath "nginx\nginx.conf"
|
||||
if (Test-Path -LiteralPath "$NginxConfPath") {
|
||||
Write-Host ">>> Configuring Nginx paths..." -ForegroundColor Yellow
|
||||
|
||||
$NginxBase = Split-Path -Parent "$NginxExe"
|
||||
$SrcMime = Join-Path -Path $NginxBase -ChildPath "conf\mime.types"
|
||||
$DestMime = Join-Path -Path $ProjectRoot -ChildPath "nginx\mime.types"
|
||||
if (-not (Test-Path -LiteralPath "$DestMime") -and (Test-Path -LiteralPath "$SrcMime")) {
|
||||
Copy-Item -Path "$SrcMime" -Destination "$DestMime" -Force
|
||||
}
|
||||
|
||||
$ForwardRoot = $ProjectRoot.Replace([char]92, [char]47)
|
||||
$FrontendDist = "$ForwardRoot/frontend/dist"
|
||||
$ImageCache = "$ForwardRoot/backend/image_cache"
|
||||
|
||||
if (-not (Test-Path -LiteralPath "$ProjectRoot/backend/image_cache")) {
|
||||
New-Item -ItemType Directory -Path "$ProjectRoot/backend/image_cache" -Force | Out-Null
|
||||
}
|
||||
|
||||
$ConfContent = Get-Content -LiteralPath "$NginxConfPath" -Raw
|
||||
$NewConfContent = $ConfContent -replace 'root\s+[^;]+;', "root `"$FrontendDist`";"
|
||||
$NewConfContent = $NewConfContent -replace 'alias\s+[^;]+;', "alias `"$ImageCache/`";"
|
||||
$BackendProxy = "http://127.0.0.1:$ServerPort"
|
||||
$NewConfContent = $NewConfContent -replace 'proxy_pass\s+http://(127\.0\.0\.1|localhost):\d+;', "proxy_pass $BackendProxy;"
|
||||
# 使用 UTF8 无 BOM 编码写入
|
||||
$Utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
||||
[System.IO.File]::WriteAllText("$NginxConfPath", $NewConfContent, $Utf8NoBom)
|
||||
}
|
||||
|
||||
# 6. Start backend
|
||||
Write-Host ">>> Launching backend (FastAPI)..." -ForegroundColor Green
|
||||
if ($UseCondaRun) {
|
||||
Write-Host ">>> Using Conda env python: $PythonExe (env=$CondaEnvName)"
|
||||
} else {
|
||||
Write-Host ">>> Using Python: $PythonExe"
|
||||
}
|
||||
|
||||
$BackendProc = Start-PythonBackground -ScriptPath "run_backend.py"
|
||||
if (-not (Assert-ProcessAlive -Process $BackendProc -DisplayName "Backend")) {
|
||||
return
|
||||
}
|
||||
|
||||
# 6.5 Start job worker
|
||||
Write-Host ">>> Launching job worker..." -ForegroundColor Green
|
||||
$WorkerProc = Start-PythonBackground -ScriptPath "run_worker.py"
|
||||
if (-not (Assert-ProcessAlive -Process $WorkerProc -DisplayName "Worker")) {
|
||||
return
|
||||
}
|
||||
|
||||
# 7. Start Nginx
|
||||
if (Test-Path -LiteralPath "$NginxExe") {
|
||||
Write-Host ">>> Launching Nginx..." -ForegroundColor Green
|
||||
$NginxDir = Split-Path -Parent "$NginxExe"
|
||||
$NginxName = Split-Path -Leaf $NginxExe
|
||||
|
||||
$SafeConfPath = $NginxConfPath.Replace([char]92, [char]47)
|
||||
$NginxArgs = @("-c", "$SafeConfPath")
|
||||
$NginxLogs = Get-BackgroundProcessLogs -ScriptPath "$NginxName"
|
||||
Write-Host " stdout -> $($NginxLogs.StdOut)"
|
||||
Write-Host " stderr -> $($NginxLogs.StdErr)"
|
||||
$NginxProc = Start-Process `
|
||||
-FilePath "$NginxExe" `
|
||||
-ArgumentList $NginxArgs `
|
||||
-WorkingDirectory "$NginxDir" `
|
||||
-PassThru `
|
||||
-NoNewWindow `
|
||||
-RedirectStandardOutput "$($NginxLogs.StdOut)" `
|
||||
-RedirectStandardError "$($NginxLogs.StdErr)"
|
||||
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
$NginxProcName = $NginxName -replace '\.exe$', ''
|
||||
$NginxRunning = Get-Process -Name $NginxProcName -ErrorAction SilentlyContinue
|
||||
|
||||
if ($NginxRunning) {
|
||||
$DisplayHost = "localhost"
|
||||
if ($ServerHost) { $DisplayHost = $ServerHost }
|
||||
Write-Host ""
|
||||
Write-StatusLine "============================================================" Green
|
||||
Write-StatusLine "SUCCESS: InSAR Management System is running!" Green
|
||||
Write-StatusLine "Frontend (via Nginx): http://$DisplayHost"
|
||||
Write-StatusLine "Backend (internal): http://127.0.0.1`:$ServerPort"
|
||||
Write-StatusLine "API Docs (internal): http://127.0.0.1`:$ServerPort/docs"
|
||||
Write-StatusLine "============================================================" Green
|
||||
Write-Host ""
|
||||
Write-StatusLine "System is running. Press Ctrl+C to stop all services." Yellow
|
||||
} else {
|
||||
Write-Warning "Nginx process not found. Check logs/nginx_error.log for details."
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Nginx executable not found at: $NginxExe"
|
||||
}
|
||||
|
||||
# 8. Wait for exit
|
||||
try {
|
||||
Write-Host ""
|
||||
Write-StatusLine "Waiting for processes (Backend PID: $($BackendProc.Id), Worker PID: $($WorkerProc.Id))..." Cyan
|
||||
|
||||
$BackgroundJob = Register-ObjectEvent -InputObject $BackendProc -EventName "Exited" -Action { Write-Host "`nBackend process exited." -ForegroundColor Red } -ErrorAction SilentlyContinue
|
||||
|
||||
Wait-Process -Id $BackendProc.Id -ErrorAction SilentlyContinue
|
||||
|
||||
} finally {
|
||||
Write-Host "`nShutting down..." -ForegroundColor Yellow
|
||||
Stop-Backend-By-Cmdline -MatchText "run_backend.py"
|
||||
Stop-Backend-By-Cmdline -MatchText "run_worker.py"
|
||||
Stop-Process-By-Name -Name $NginxProcName -ExeName $NginxExe
|
||||
Write-Host "Done." -ForegroundColor Green
|
||||
}
|
||||
Reference in New Issue
Block a user