From b68013b2f2daf2158f48aa8865705c4c33ac0f72 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sun, 22 Feb 2026 16:38:53 +0300 Subject: [PATCH] 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 --- .claude/skills/web-info/scripts/web-info.ps1 | 19 +++++++-- .../web-publish/scripts/web-publish.ps1 | 41 +++++++++++++++++-- .claude/skills/web-stop/scripts/web-stop.ps1 | 29 +++++++++---- .../web-unpublish/scripts/web-unpublish.ps1 | 13 ++++-- 4 files changed, 84 insertions(+), 18 deletions(-) diff --git a/.claude/skills/web-info/scripts/web-info.ps1 b/.claude/skills/web-info/scripts/web-info.ps1 index 75f8efdb..615fcd43 100644 --- a/.claude/skills/web-info/scripts/web-info.ps1 +++ b/.claude/skills/web-info/scripts/web-info.ps1 @@ -46,14 +46,25 @@ if (-not (Test-Path $httpdExe)) { exit 0 } -# --- Check process --- -$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue -if ($httpdProc) { - $pids = ($httpdProc | ForEach-Object { $_.Id }) -join ", " +# --- Check process (only our Apache) --- +$httpdExeNorm = (Resolve-Path $httpdExe -ErrorAction SilentlyContinue).Path +$ourProc = Get-Process httpd -ErrorAction SilentlyContinue | Where-Object { + 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 } else { 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" diff --git a/.claude/skills/web-publish/scripts/web-publish.ps1 b/.claude/skills/web-publish/scripts/web-publish.ps1 index 2f5f7063..deb2c45a 100644 --- a/.claude/skills/web-publish/scripts/web-publish.ps1 +++ b/.claude/skills/web-publish/scripts/web-publish.ps1 @@ -298,14 +298,43 @@ if ($confContent -match [regex]::Escape($pubMarkerStart)) { [System.IO.File]::WriteAllText($confFile, $confContent) 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 --- -$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue +$httpdProc = Get-OurHttpd if ($httpdProc) { Write-Host "Apache уже запущен (PID: $(($httpdProc | Select-Object -First 1).Id))" -ForegroundColor Yellow Write-Host "Перезапуск для применения конфигурации..." - # Portable Apache: stop + start $httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue 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..." @@ -313,11 +342,17 @@ Start-Process -FilePath $httpdExe -WorkingDirectory $ApachePath -WindowStyle Hid Start-Sleep -Seconds 2 -$httpdCheck = Get-Process httpd -ErrorAction SilentlyContinue +$httpdCheck = Get-OurHttpd if ($httpdCheck) { Write-Host "Apache запущен (PID: $(($httpdCheck | Select-Object -First 1).Id))" -ForegroundColor Green } else { 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" if (Test-Path $errorLog) { Write-Host "--- error.log (последние 10 строк) ---" -ForegroundColor Yellow diff --git a/.claude/skills/web-stop/scripts/web-stop.ps1 b/.claude/skills/web-stop/scripts/web-stop.ps1 index bf5aa66e..949b0789 100644 --- a/.claude/skills/web-stop/scripts/web-stop.ps1 +++ b/.claude/skills/web-stop/scripts/web-stop.ps1 @@ -33,17 +33,32 @@ if (-not $ApachePath) { $ApachePath = Join-Path $projectRoot "tools\apache24" } -# --- Check process --- -$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue +# --- Helper: filter httpd processes by our ApachePath --- +$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) { - 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 } $pids = ($httpdProc | ForEach-Object { $_.Id }) -join ", " Write-Host "Останавливаю Apache (PID: $pids)..." -# --- Stop processes --- +# --- Stop our processes --- $httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue # --- Wait for shutdown --- @@ -52,7 +67,7 @@ $elapsed = 0 while ($elapsed -lt $maxWait) { Start-Sleep -Seconds 1 $elapsed++ - $check = Get-Process httpd -ErrorAction SilentlyContinue + $check = Get-OurHttpd if (-not $check) { Write-Host "Apache остановлен" -ForegroundColor Green exit 0 @@ -60,12 +75,12 @@ while ($elapsed -lt $maxWait) { } # --- Fallback: force kill --- -$remaining = Get-Process httpd -ErrorAction SilentlyContinue +$remaining = Get-OurHttpd if ($remaining) { Write-Host "Принудительная остановка..." -ForegroundColor Yellow $remaining | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 - $final = Get-Process httpd -ErrorAction SilentlyContinue + $final = Get-OurHttpd if ($final) { Write-Host "Error: не удалось остановить Apache" -ForegroundColor Red exit 1 diff --git a/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 b/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 index c4265596..d07651d9 100644 --- a/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 +++ b/.claude/skills/web-unpublish/scripts/web-unpublish.ps1 @@ -81,11 +81,14 @@ if (Test-Path $publishDir) { Write-Host "Каталог не найден: $publishDir" -ForegroundColor Yellow } -# --- Restart Apache if running --- -$httpdProc = Get-Process httpd -ErrorAction SilentlyContinue +# --- Restart Apache if running (only our instance) --- +$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) { Write-Host "Перезапуск Apache..." - $httpdExe = Join-Path (Join-Path $ApachePath "bin") "httpd.exe" $httpdProc | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 @@ -93,7 +96,9 @@ if ($httpdProc) { if ($remainingPubs.Count -gt 0) { Start-Process -FilePath $httpdExe -WorkingDirectory $ApachePath -WindowStyle Hidden 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) { Write-Host "Apache перезапущен" -ForegroundColor Green } else {