fix(web): port check, process isolation, startup diagnostics

- web-publish: check port availability before starting, show which process
  holds it; run httpd -t on startup failure for diagnostics
- All scripts: filter httpd processes by path (Resolve-Path match) to avoid
  killing or misidentifying a global Apache installation
- web-info: warn about foreign httpd processes
- web-stop: only stop our Apache instance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-02-22 16:38:53 +03:00
co-authored by Claude Opus 4.6
parent e2f765fcc0
commit b68013b2f2
4 changed files with 84 additions and 18 deletions
+15 -4
View File
@@ -46,14 +46,25 @@ if (-not (Test-Path $httpdExe)) {
exit 0 exit 0
} }
# --- Check process --- # --- Check process (only our Apache) ---
$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue $httpdExeNorm = (Resolve-Path $httpdExe -ErrorAction SilentlyContinue).Path
if ($httpdProc) { $ourProc = Get-Process httpd -ErrorAction SilentlyContinue | Where-Object {
$pids = ($httpdProc | ForEach-Object { $_.Id }) -join ", " try { $_.Path -eq $httpdExeNorm } catch { $false }
}
$foreignProc = Get-Process httpd -ErrorAction SilentlyContinue | Where-Object {
try { $_.Path -ne $httpdExeNorm } catch { $true }
}
if ($ourProc) {
$pids = ($ourProc | ForEach-Object { $_.Id }) -join ", "
Write-Host "Status: Запущен (PID: $pids)" -ForegroundColor Green Write-Host "Status: Запущен (PID: $pids)" -ForegroundColor Green
} else { } else {
Write-Host "Status: Остановлен" -ForegroundColor Yellow Write-Host "Status: Остановлен" -ForegroundColor Yellow
} }
if ($foreignProc) {
$fpid = ($foreignProc | Select-Object -First 1).Id
$fpath = try { ($foreignProc | Select-Object -First 1).Path } catch { "?" }
Write-Host "[WARN] Обнаружен сторонний Apache (PID: $fpid, $fpath)" -ForegroundColor Yellow
}
Write-Host "Path: $ApachePath" Write-Host "Path: $ApachePath"
@@ -298,14 +298,43 @@ if ($confContent -match [regex]::Escape($pubMarkerStart)) {
[System.IO.File]::WriteAllText($confFile, $confContent) [System.IO.File]::WriteAllText($confFile, $confContent)
Write-Host "httpd.conf обновлён" -ForegroundColor Green Write-Host "httpd.conf обновлён" -ForegroundColor Green
# --- Helper: filter httpd processes by our ApachePath ---
function Get-OurHttpd {
$httpdExeNorm = (Resolve-Path $httpdExe -ErrorAction SilentlyContinue).Path
Get-Process httpd -ErrorAction SilentlyContinue | Where-Object {
try { $_.Path -eq $httpdExeNorm } catch { $false }
}
}
# --- Check port availability ---
$portCheck = Get-NetTCPConnection -LocalPort $Port -ErrorAction SilentlyContinue | Select-Object -First 1
if ($portCheck) {
$ourProc = Get-OurHttpd
if ($ourProc) {
# Our Apache holds the port — will restart
} else {
$holder = Get-Process -Id $portCheck.OwningProcess -ErrorAction SilentlyContinue
$holderName = if ($holder) { "$($holder.ProcessName) (PID: $($holder.Id))" } else { "PID $($portCheck.OwningProcess)" }
Write-Host "Error: порт $Port занят процессом $holderName" -ForegroundColor Red
Write-Host "Укажите другой порт: -Port 9090" -ForegroundColor Yellow
exit 1
}
}
# --- Start Apache if not running --- # --- Start Apache if not running ---
$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue $httpdProc = Get-OurHttpd
if ($httpdProc) { if ($httpdProc) {
Write-Host "Apache уже запущен (PID: $(($httpdProc | Select-Object -First 1).Id))" -ForegroundColor Yellow Write-Host "Apache уже запущен (PID: $(($httpdProc | Select-Object -First 1).Id))" -ForegroundColor Yellow
Write-Host "Перезапуск для применения конфигурации..." Write-Host "Перезапуск для применения конфигурации..."
# Portable Apache: stop + start
$httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue $httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1 Start-Sleep -Seconds 1
} else {
# Check if a foreign httpd holds the port
$foreignHttpd = Get-Process httpd -ErrorAction SilentlyContinue
if ($foreignHttpd) {
Write-Host "[WARN] Обнаружен сторонний Apache (PID: $(($foreignHttpd | Select-Object -First 1).Id))" -ForegroundColor Yellow
Write-Host " Наш Apache: $httpdExe" -ForegroundColor Yellow
}
} }
Write-Host "Запуск Apache..." Write-Host "Запуск Apache..."
@@ -313,11 +342,17 @@ Start-Process -FilePath $httpdExe -WorkingDirectory $ApachePath -WindowStyle Hid
Start-Sleep -Seconds 2 Start-Sleep -Seconds 2
$httpdCheck = Get-Process httpd -ErrorAction SilentlyContinue $httpdCheck = Get-OurHttpd
if ($httpdCheck) { if ($httpdCheck) {
Write-Host "Apache запущен (PID: $(($httpdCheck | Select-Object -First 1).Id))" -ForegroundColor Green Write-Host "Apache запущен (PID: $(($httpdCheck | Select-Object -First 1).Id))" -ForegroundColor Green
} else { } else {
Write-Host "Apache не удалось запустить" -ForegroundColor Red Write-Host "Apache не удалось запустить" -ForegroundColor Red
# Run config test for diagnostics
$testResult = & $httpdExe -t 2>&1
if ($testResult) {
Write-Host "--- httpd -t ---" -ForegroundColor Yellow
$testResult | ForEach-Object { Write-Host " $_" }
}
$errorLog = Join-Path (Join-Path $ApachePath "logs") "error.log" $errorLog = Join-Path (Join-Path $ApachePath "logs") "error.log"
if (Test-Path $errorLog) { if (Test-Path $errorLog) {
Write-Host "--- error.log (последние 10 строк) ---" -ForegroundColor Yellow Write-Host "--- error.log (последние 10 строк) ---" -ForegroundColor Yellow
+22 -7
View File
@@ -33,17 +33,32 @@ if (-not $ApachePath) {
$ApachePath = Join-Path $projectRoot "tools\apache24" $ApachePath = Join-Path $projectRoot "tools\apache24"
} }
# --- Check process --- # --- Helper: filter httpd processes by our ApachePath ---
$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue $httpdExe = Join-Path (Join-Path $ApachePath "bin") "httpd.exe"
$httpdExeNorm = (Resolve-Path $httpdExe -ErrorAction SilentlyContinue).Path
function Get-OurHttpd {
Get-Process httpd -ErrorAction SilentlyContinue | Where-Object {
try { $_.Path -eq $httpdExeNorm } catch { $false }
}
}
# --- Check process (only our Apache) ---
$httpdProc = Get-OurHttpd
if (-not $httpdProc) { if (-not $httpdProc) {
Write-Host "Apache не запущен" -ForegroundColor Yellow $foreign = Get-Process httpd -ErrorAction SilentlyContinue
if ($foreign) {
Write-Host "Наш Apache не запущен" -ForegroundColor Yellow
Write-Host "[WARN] Обнаружен сторонний Apache (PID: $(($foreign | Select-Object -First 1).Id))" -ForegroundColor Yellow
} else {
Write-Host "Apache не запущен" -ForegroundColor Yellow
}
exit 0 exit 0
} }
$pids = ($httpdProc | ForEach-Object { $_.Id }) -join ", " $pids = ($httpdProc | ForEach-Object { $_.Id }) -join ", "
Write-Host "Останавливаю Apache (PID: $pids)..." Write-Host "Останавливаю Apache (PID: $pids)..."
# --- Stop processes --- # --- Stop our processes ---
$httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue $httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue
# --- Wait for shutdown --- # --- Wait for shutdown ---
@@ -52,7 +67,7 @@ $elapsed = 0
while ($elapsed -lt $maxWait) { while ($elapsed -lt $maxWait) {
Start-Sleep -Seconds 1 Start-Sleep -Seconds 1
$elapsed++ $elapsed++
$check = Get-Process httpd -ErrorAction SilentlyContinue $check = Get-OurHttpd
if (-not $check) { if (-not $check) {
Write-Host "Apache остановлен" -ForegroundColor Green Write-Host "Apache остановлен" -ForegroundColor Green
exit 0 exit 0
@@ -60,12 +75,12 @@ while ($elapsed -lt $maxWait) {
} }
# --- Fallback: force kill --- # --- Fallback: force kill ---
$remaining = Get-Process httpd -ErrorAction SilentlyContinue $remaining = Get-OurHttpd
if ($remaining) { if ($remaining) {
Write-Host "Принудительная остановка..." -ForegroundColor Yellow Write-Host "Принудительная остановка..." -ForegroundColor Yellow
$remaining | Stop-Process -Force -ErrorAction SilentlyContinue $remaining | Stop-Process -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1 Start-Sleep -Seconds 1
$final = Get-Process httpd -ErrorAction SilentlyContinue $final = Get-OurHttpd
if ($final) { if ($final) {
Write-Host "Error: не удалось остановить Apache" -ForegroundColor Red Write-Host "Error: не удалось остановить Apache" -ForegroundColor Red
exit 1 exit 1
@@ -81,11 +81,14 @@ if (Test-Path $publishDir) {
Write-Host "Каталог не найден: $publishDir" -ForegroundColor Yellow Write-Host "Каталог не найден: $publishDir" -ForegroundColor Yellow
} }
# --- Restart Apache if running --- # --- Restart Apache if running (only our instance) ---
$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue $httpdExe = Join-Path (Join-Path $ApachePath "bin") "httpd.exe"
$httpdExeNorm = (Resolve-Path $httpdExe -ErrorAction SilentlyContinue).Path
$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue | Where-Object {
try { $_.Path -eq $httpdExeNorm } catch { $false }
}
if ($httpdProc) { if ($httpdProc) {
Write-Host "Перезапуск Apache..." Write-Host "Перезапуск Apache..."
$httpdExe = Join-Path (Join-Path $ApachePath "bin") "httpd.exe"
$httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue $httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1 Start-Sleep -Seconds 1
@@ -93,7 +96,9 @@ if ($httpdProc) {
if ($remainingPubs.Count -gt 0) { if ($remainingPubs.Count -gt 0) {
Start-Process -FilePath $httpdExe -WorkingDirectory $ApachePath -WindowStyle Hidden Start-Process -FilePath $httpdExe -WorkingDirectory $ApachePath -WindowStyle Hidden
Start-Sleep -Seconds 2 Start-Sleep -Seconds 2
$check = Get-Process httpd -ErrorAction SilentlyContinue $check = Get-Process httpd -ErrorAction SilentlyContinue | Where-Object {
try { $_.Path -eq $httpdExeNorm } catch { $false }
}
if ($check) { if ($check) {
Write-Host "Apache перезапущен" -ForegroundColor Green Write-Host "Apache перезапущен" -ForegroundColor Green
} else { } else {