fix(web-info): имя журнала ошибок из httpd.conf + описание вывода вместо примера

Секция «Последние ошибки» всегда печатала «(нет файла)»: путь был захардкожен
как logs/error.log, а сборка Apache пишет logs/error_log. Имя берём из директивы
ErrorLog, с фолбэком на оба общепринятых имени.

В SKILL.md дословный пример вывода заменён легендой: модель и так видит реальный
stdout, ей нужна семантика тегов и признаков, а не их копия (и копия дрейфует).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-08 15:28:20 +03:00
co-authored by Claude Opus 5
parent fbf4d4f986
commit 88535a759b
3 changed files with 45 additions and 18 deletions
+15 -14
View File
@@ -35,24 +35,25 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-info.ps1" <па
|----------|:------------:|----------|
| `-ApachePath <путь>` | нет | Корень Apache (по умолчанию `tools/apache24`) |
## Формат вывода
## Как читать вывод
```
=== Apache Web Server ===
Status: Запущен (PID: 12345)
Path: C:\...\tools\apache24
Port: 8081
Module: C:/Program Files/1cv8/8.3.24.1691/bin/wsap24.dll
Три секции: состояние сервера, список публикаций (имя, URL, строка соединения, теги сервисов),
хвост журнала Apache.
=== Опубликованные базы ===
mydb http://localhost:8081/mydb File="C:\Bases\MyDB"; [WS+ext HTTP+ext OData]
| В выводе | Что значит |
|----------|------------|
| `Status: Остановлен` | Apache не запущен — публикации в `httpd.conf` есть, но URL-ы не отвечают. Поднимается повторным `/web-publish` |
| `[WARN] Обнаружен сторонний Apache` | На машине работает чужой экземпляр — может держать порт; наши команды им не управляют |
| `[WS HTTP OData]` | Что опубликовано для базы: SOAP-сервисы, HTTP-сервисы, стандартный OData |
| `+ext` (`WS+ext`) | Публикуются и сервисы, поставляемые расширениями конфигурации |
| `(нет публикаций)` | Apache стоит, но ни одна база не опубликована — нужен `/web-publish` |
| `(пусто)` / `(нет файла)` в ошибках | Норма, а не сбой: журнал пуст или ещё не создан |
=== Последние ошибки ===
(пусто)
```
Секция ошибок — последние строки журнала Apache, в том числе информационные (`notice` при старте).
Наличие строк само по себе о проблеме не говорит — смотри уровень (`error`, `warn`).
В скобках — что опубликовано для базы: `WS` (SOAP), `HTTP` (HTTP-сервисы), `OData`.
Суффикс `+ext` — публикуются и сервисы, поставляемые расширениями конфигурации.
Публикация в списке не означает, что база отвечает: `/web-info` читает `httpd.conf` и дескрипторы,
а не опрашивает URL-ы. Если нужно убедиться — дёрни URL.
## Примеры
+18 -2
View File
@@ -144,8 +144,24 @@ if ($pubMatches.Count -eq 0) {
Write-Host ""
Write-Host "=== Последние ошибки ===" -ForegroundColor Cyan
$errorLog = Join-Path (Join-Path $ApachePath "logs") "error.log"
if (Test-Path $errorLog) {
# Имя файла берём из httpd.conf: сборки Apache расходятся (error.log / error_log)
$errorLog = $null
if ($confContent -match '(?m)^\s*ErrorLog\s+"?([^"\r\n]+)"?') {
$logPath = $Matches[1].Trim()
if ([System.IO.Path]::IsPathRooted($logPath)) {
$errorLog = $logPath
} else {
$errorLog = Join-Path $ApachePath ($logPath -replace '/','\')
}
}
if (-not $errorLog -or -not (Test-Path $errorLog)) {
$errorLog = @("error_log", "error.log") |
ForEach-Object { Join-Path (Join-Path $ApachePath "logs") $_ } |
Where-Object { Test-Path $_ } |
Select-Object -First 1
}
if ($errorLog -and (Test-Path $errorLog)) {
$lines = Get-Content $errorLog -Tail 5 -ErrorAction SilentlyContinue
if ($lines -and $lines.Count -gt 0) {
foreach ($line in $lines) {
+12 -2
View File
@@ -146,8 +146,18 @@ def main():
print('')
print('=== Последние ошибки ===')
error_log = os.path.join(apache_path, 'logs', 'error.log')
if os.path.exists(error_log):
# Имя файла берём из httpd.conf: сборки Apache расходятся (error.log / error_log)
error_log = None
m_log = re.search(r'(?m)^\s*ErrorLog\s+"?([^"\r\n]+)"?', conf_content)
if m_log:
log_path = m_log.group(1).strip()
error_log = log_path if os.path.isabs(log_path) else os.path.join(apache_path, log_path)
if not error_log or not os.path.exists(error_log):
error_log = next((p for p in (os.path.join(apache_path, 'logs', n)
for n in ('error_log', 'error.log'))
if os.path.exists(p)), None)
if error_log and os.path.exists(error_log):
try:
with open(error_log, 'r', encoding='utf-8-sig', errors='replace') as f:
all_lines = f.readlines()