Логи Apache (ч. 2): Формат логов ошибок. Журнал событий модулей


Оглавление: Всё о логах Apache — от настройки до анализа

1. Виды и модули журналов. Формат логов доступа Apache

2. Формат логов ошибок. Журнал событий модулей

2.1 Логи ошибок Apache

2.2 Директива ErrorLog

2.3 Директива ErrorLogFormat

2.4 Директива LogLevel

2.5 Директива LogLevelOverride

2.6 Журнал событий модулей

3. Программы для анализа логов Apache

4. Криминалистические логи

5. Дополнительные настраиваемые журналы отладки. Журналы выполнения CGI скриптов


Логи ошибок Apache

Журнал ошибок сервера, имя и местоположение которого задаётся директивой ErrorLog, является наиболее важным файлом журнала. Это место, куда Apache httpd будет отправлять диагностическую информацию и записывать любые ошибки, с которыми он сталкивается при обработке запросов. Это первое место, где нужно посмотреть, когда возникает проблема с запуском сервера или работой сервера, поскольку он часто содержит подробности о том, что пошло не так и как это исправить.

Журнал ошибок обычно записывается в файл (обычно error_log в системах Unix и error.log в Windows и OS/2). В системах Unix также возможно, чтобы сервер отправлял ошибки в системный журнал или передавал их программе.

Формат журнала ошибок определяется директивой ErrorLogFormat, с помощью которой вы можете настроить, какие значения записываются в журнал. Если вы его не указали, то используется значение по умолчанию. Типичное сообщение журнала следующее:

[Sun Aug 18 12:43:09.867536 2019] [authz_core:error] [pid 30395] [client 144.76.28.10:42847] AH01630: client denied by server configuration: /srv/http/suip/ru/, referer: https://suip.biz/ru/?act=proxy2

Первый элемент в записи журнала — это дата и время сообщения. Следующим является модуль, создающий сообщение (в данном случае authz_core) и уровень серьёзности этого сообщения. За этим следует идентификатор процесса и, если необходимо, идентификатор потока процесса, в котором возникло условие. Далее у нас есть адрес клиента, который сделал запрос (его IP адрес и номер порта, с которого открыто соединение). И, наконец, подробное сообщение об ошибке, которое в этом случае сервер отклонил подключение.

В журнале ошибок может появиться очень большое количество различных сообщений. Большинство выглядит похожим на пример выше. Журнал ошибок также будет содержать отладочную информацию из сценариев CGI. Любая информация, записанная в stderr сценарием CGI, будет скопирована непосредственно в журнал ошибок.

Если поместить токен %L в журнал ошибок и журнал доступа, будет создан идентификатор записи журнала, с которым вы можете сопоставить запись в журнале ошибок с записью в журнале доступа. Если загружен mod_unique_id, его уникальный идентификатор запроса также будет использоваться в качестве идентификатора записи журнала.

Во время тестирования часто бывает полезно постоянно отслеживать журнал ошибок на наличие проблем. В системах Unix вы можете сделать это, используя команду вида:

tail -f /путь/до/журнала/ошибок

Например:

tail -f /var/log/httpd/error_log

Директива ErrorLog

Описание: устанавливает место, куда сервер будет записывать ошибки.


Синтаксис:

ErrorLog путь-до-файла|syslog[:[facility][:tag]]

Значение по умолчанию:

ErrorLog logs/error_log   # (Unix)
ErrorLog logs/error.log   #(Windows and OS/2)

Контекст: server config, виртуальные хосты.

Директива ErrorLog устанавливает имя файла, в который сервер будет вести журнал любых ошиббок, с которыми он сталкивается. Если путь к файлу не является абсолютным, предполагается, что он указан относительно ServerRoot.

ErrorLog "/var/log/httpd/error_log"

Если путь-до-файла начинается с символа труба "|" тогда предполагается, что это команда для вызова журнала ошибок.

ErrorLog "|/usr/local/bin/httpd_errors"

Смотрите подробности в разделе «Конвейерная обработка».

Использование syslog вместо имени файла позволяет регистрироваться через syslogd(8), если система поддерживает его и если загружен mod_syslog. По умолчанию используется средство syslog local7, но вы можете переопределить это, используя синтаксис syslog:средство, где средство может быть одним из имён, обычно задокументированных в syslog(1). Средство фактически является глобальным, и если оно изменяется на отдельных виртуальных хостах, указанное последнее средство влияет на весь сервер. Те же правила применяются к тегу syslog, который по умолчанию использует двоичное имя Apache, в большинстве случаев httpd. Вы также можете переопределить это, используя синтаксис syslog::tag.

ErrorLog syslog:user
ErrorLog syslog:user:httpd.srv1
ErrorLog syslog::httpd.srv2

Дополнительные модули могут предоставлять свои собственные поставщики ErrorLog. Синтаксис похож на пример системного журнала выше.

БЕЗОПАСНОСТЬ: см. раздел «Вопросы безопасности», чтобы узнать, почему ваша безопасность может быть скомпрометирована, если каталог, в котором хранятся файлы журналов, доступен для записи кому-либо, кроме пользователя, запускающего сервер.

Примечание: при вводе пути к файлу на платформах, отличных от Unix, необходимо следить за тем, чтобы использовались только прямые косые черты, даже если платформа может разрешать использование обратных косых черт. В целом, рекомендуется всегда использовать прямую косую черту в файлах конфигурации.

Директива ErrorLogFormat

Описание: Определение формата для записей журнала ошибок.

Синтаксис:

ErrorLogFormat [connection|request] format

Контекст: server config, виртуальные хосты.

ErrorLogFormat позволяет указать, какая дополнительная информация записывается в журнал ошибок в дополнение к фактическому сообщению журнала.

#Простой пример
ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M"

Указание соединения или запроса в качестве первого параметра позволяет указать дополнительные форматы, в результате чего регистрируется дополнительная информация, когда первое сообщение регистрируется для определённого соединения или запроса, соответственно. Эта дополнительная информация регистрируется только один раз за соединение/запрос. Если соединение или запрос обрабатываются без какого-либо сообщения журнала, дополнительная информация также не регистрируется.


Может случиться, что некоторые элементы строки формата не производят вывод. Например, заголовок Referer присутствует только в том случае, если сообщение журнала связано с запросом, а сообщение журнала появляется в тот момент, когда заголовок Referer уже был считан с клиента. Если выходные данные не создаются, поведение по умолчанию заключается в удалении всего, начиная с предыдущего пробела до следующего пробела. Это означает, что строка журнала неявно разделена на поля в переходах между не белыми пробелами и белыми пробелами. Если элемент строки формата не производит вывод, все поле опускается. Например, если удалённый адрес %a в формате журнала [%t] [%l] [%a] %M недоступен, окружающие скобки также не регистрируются. Символы пробела можно экранировать с помощью обратной косой черты, чтобы они не могли ограничить поле. Комбинация '% ' (процент и пробел) — это разделитель поля нулевой ширины, который не производит никакого вывода.

Вышеуказанное поведение можно изменить, добавив модификаторы к элементу строки формата. Модификатор (минус) приводит к записи минуса, если соответствующий элемент не производит никакого вывода. В форматах один-раз-на-соединение/запрос также можно использовать модификатор + (плюс). Если элемент с модификатором плюс не производит никакого вывода, вся строка опускается.

Число в качестве модификатора может использоваться для назначения уровня серьёзности журнала элементу формата. Элемент будет зарегистрирован только в том случае, если серьёзность сообщения журнала не выше указанного уровня серьёзности журнала. Число может варьироваться от 1 (alert) до 4 (warn) и 7 (debug) до 15 (trace8).

Например, вот что произойдёт, если вы добавите модификаторы в токен %{Referer}i, который регистрирует заголовок запроса Referer.

Модифицированный токен Значение
%-{Referer}i Регистрирует — если Referer не установлен.
%+{Referer}i Опускает всю строку, если Referer не установлен.
%4{Referer}i Регистрирует Реферер только в том случае, если серьёзность сообщения журнала выше 4.

Некоторые элементы строки формата принимают дополнительные параметры в фигурных скобках.

Строка формата Описание
%% Буквальный знак процента.
%a Клиентский IP адрес запроса (смотрите также модуль mod_remoteip).
%{c}a Лежащий в основе IP-адрес соединения (см. модуль mod_remoteip).
%A Локальный IP-адрес.
%{ИМЯ}e Содержимое переменной окружения запрос с ИМЕНЕМ.
%E Код состояния и строка ошибки APR/OS
%F Имя исходного файла и номер строки журнала вызовов
%{ИМЯ}i ИМЯ заголовка запроса
%k Количество запросов подтверждения активности (keep-alive) для этого соединения
%l Лог-уровень сообщения
%L Лог ID запроса
%{c}L Лог ID соединения
%{C}L Идентификатор журнала соединения, если используется в области соединения, в противном случае пусто
%m Имя модуля, регистрирующего сообщение
%M Фактическое сообщение журнала
%{ИМЯ}n Идентификатор процесса текущего процесса
%P Идентификатор дочернего процесса, который обслуживал запрос.
%T Идентификатор текущего процесса
%{g}T Уникальный системный идентификатор текущего потока (тот же идентификатор, который отображается, например, top; в настоящее время только в Linux)
%t Текущее время
%{u}t Текущее время, включая микросекунды
%{cu}t Текущее время в компактном формате ISO 8601, включая микросекунды
%v Каноническое ServerName сервера, обслуживающего запрос.
%V Имя сервера в соответствии с настройкой UseCanonicalName.
 (обратный слэш и пробел) Пробельный разделитель без создания нового поля (разделитель внутри одного поля, пробел внутри поля)
% (процент и пробел) Разделитель полей (без вывода)

Формат идентификатора журнала %L создаёт уникальный идентификатор для соединения или запроса. Это можно использовать для сопоставления того, какие строки журнала принадлежат тому же соединению или запросу, какой запрос происходит с каким соединением. Строка формата %L также доступна в mod_log_config, чтобы позволить соотносить записи журнала доступа со строками журнала ошибок. Если загружен mod_unique_id, его уникальный идентификатор будет использоваться в качестве идентификатора журнала для запросов.


#Пример (формат по умолчанию для MPM потоков)
ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"

Это может привести к сообщениям об ошибках, таких как:

[Thu May 12 08:28:57.652118 2011] [core:error] [pid 8777:tid 4326490112] [client ::1:58619] File does not exist: /usr/local/apache2/htdocs/favicon.ico

Обратите внимание, что, как обсуждалось выше, некоторые поля полностью опущены, поскольку они не определены.

#Пример (похож на формат 2.2.x)
ErrorLogFormat "[%t] [%l] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"
#Расширенный пример с идентификаторами журнала запросов/подключений
ErrorLogFormat "[%{uc}t] [%-m:%-l] [R:%L] [C:%{C}L] %7F: %E: %M"
ErrorLogFormat request "[%{uc}t] [R:%L] Request %k on C:%{c}L pid:%P tid:%T"
ErrorLogFormat request "[%{uc}t] [R:%L] UA:'%+{User-Agent}i'"
ErrorLogFormat request "[%{uc}t] [R:%L] Referer:'%+{Referer}i'"
ErrorLogFormat connection "[%{uc}t] [C:%{c}L] local\ %a remote\ %A"

Директива LogLevel

Описание: Контролирует вербальность ErrorLog.

Синтаксис:

LogLevel [модуль:]уровень [модуль:уровень] ...

Значение по умолчанию:

LogLevel warn

Контекст: server config, виртуальные хосты, директории

Совместимость: Настройка на уровне модулей и на уровне директорий доступны в Apache HTTP Server 2.3.6 и более поздних.

LogLevel регулирует подробность сообщений, записываемых в журналах ошибок (см. директиву ErrorLog). Доступны следующие уровни в порядке убывания значимости:

Уровень Описание Пример
emerg Чрезвычайные ситуации — система не работоспособна. "Child cannot open lock file. Exiting"
alert Действие должно быть принято немедленно. "getpwuid: couldn't determine user name from uid"
crit Критические условия. "socket: Failed to get a socket, exiting child"
error Ошибки. "Premature end of script headers"
warn Предупреждения. "child process 1234 did not exit, sending another SIGHUP"
notice Нормальное, но значимое состояние. "httpd: caught SIGBUS, attempting to dump core in …"
info Информационные сообщения. "Server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers)…"
debug Сообщения уровня отладки. "Opening config file …"
trace1 Трассировочные сообщения. "proxy: FTP: control connection complete"
trace2 Трассировочные сообщения. "proxy: CONNECT: sending the CONNECT request to the remote proxy"
trace3 Трассировочные сообщения. "openssl: Handshake: start"
trace4 Трассировочные сообщения. "read from buffered SSL brigade, mode 0, 17 bytes"
trace5 Трассировочные сообщения. "map lookup FAILED: map=rewritemap key=keyname"
trace6 Трассировочные сообщения. "cache lookup FAILED, forcing new map lookup"
trace7 Трассировочные сообщения, сброс больших объёмов данных. "| 0000: 02 23 44 30 13 40 ac 34 df 3d bf 9a 19 49 39 15 |"
trace8 Трассировочные сообщения, сброс больших объёмов данных. "| 0000: 02 23 44 30 13 40 ac 34 df 3d bf 9a 19 49 39 15 |"

Если указан определённый уровень, сообщения со всех других уровней более высокой значимости будут также сообщаться. Например, если указано


LogLevel info

то также будут публиковаться сообщения с уровнями notice и warn.

Обратите внимание, что сообщения об ошибках 404 (файл не найден), которые генерирует сам веб-сервер (core), имеют статус info:

[Mon Aug 19 05:21:07.846623 2019] [core:info] [pid 29057] [client 2604:a880:2:d0::651:5001:50864] AH00128: File does not exist: /srv/http/suip/.well-known/security.txt

Это означает, что при настройках по умолчанию (LogLevel установлена на warn) запросы, завершившиеся статусом 404 не будут попадать в журналы ошибок! Чтобы это исправить, нужно установить уровень на info:

LogLevel info

Обратите внимание, что если не найден файл, который обрабатывается другим модулем, то этот модуль может установить свой собственный уровень. К примеру, модуль php7, если не найден PHP скрипт, установит для такого сообщения уровень серьёзности error и такая запись попадёт в журнал ошибок даже при настройках по умолчанию:

[Mon Aug 19 05:26:02.847140 2019] [php7:error] [pid 29256] [client 115.28.240.215:1920] script '/srv/http/suip/wp-login.php' not found or unable to stat

Подробности смотрите в статье «Почему в логах ошибок Apache не сохраняются записи об ошибке 404».

Рекомендуется использовать уровень как минимум crit (или более низкой значимости).

Например:

LogLevel notice

Примечание: при записе в обычный файл сообщения с уведомлением с уровнем notice не могут быть подавлены и, следовательно, всегда регистрируются. Однако это не относится к случаям, когда регистрация ведётся с использованием syslog.

Указание уровня без имени модуля приведёт к сбросу уровня для всех модулей до этого уровня. Указание уровня с именем модуля установит уровень только для этого модуля. Можно использовать имя исходного файла модуля, идентификатор модуля или идентификатор модуля с конечным _module, опущенным в качестве спецификации модуля. Это означает, что следующие три спецификации эквивалентны:

LogLevel info ssl:warn
LogLevel info mod_ssl.c:warn
LogLevel info ssl_module:warn

Также возможно изменить уровень для каждого каталога:

LogLevel info
<Directory "/usr/local/apache/htdocs/app">
  LogLevel debug
</Directory>

Конфигурация на уровне каталога для каждого каталога влияет только на сообщения, которые регистрируются после анализа запроса и связаны с ним. Сообщения журнала, связанные с сервером или соединением, не затрагиваются. Однако на последние может повлиять директива LogLevelOverride.

Директива LogLevelOverride

Описание: Переопределить вербальность ErrorLog для определённых клиентов.

Синтаксис:

LogLevel IP_адрес[/префикс_диапазона] [модуль:]уровень [модуль:уровень] ...

Значение по умолчанию: не установлено.

Контекст: server config, виртуальные хосты.

Совместимость: Доступна в Apache HTTP Server 2.5.0 и более поздних.

LogLevelOverride настраивает LogLevel для запросов, поступающих с определённых клиентских IP-адресов. Это позволяет включить подробное ведение журнала только для определённых тестовых клиентов. IP-адрес проверяется в очень раннем состоянии при обработке соединения. Следовательно, LogLevelOverride позволяет изменить уровень журнала для таких вещей, как рукопожатие SSL, которые происходят до того, как будет оценена директива LogLevel в контейнере <If>.

LogLevelOverride принимает либо один IP-адрес, либо спецификацию IP-адресов CIDR/длина_подсети. Синтаксис спецификации loglevel см. в разделе Директива LogLevel.

Для запросов, соответствующих директиве LogLevelOverride, спецификации LogLevel для каждого каталога игнорируются.

Примеры:

LogLevelOverride 192.0.2.0/24 ssl:trace6
    LogLevelOverride 192.0.2.7 ssl:trace8

LogLevelOverride влияет только на сообщения журнала, связанные с запросом или соединением. Сообщения журнала, связанные с сервером, не затрагиваются.

Журнал событий модулей

Директива LogLevel позволяет вам указывать пороговый уровень важности попадания записи в журнал для каждого модуля. Таким образом, если вы устраняете проблему только с одним конкретным модулем, вы можете увеличить объем его информации в журнале, не получая в довесок информацию о других модулях, которые вас не интересуют. Это особенно полезно для таких модулей, как mod_proxy или mod_rewrite где вы хотите узнать подробности о том, что они пытаются сделать, и что в них происходит.

Сделайте это, указав имя модуля в вашей директиве LogLevel:

LogLevel info rewrite:trace5

Это устанавливает для основного LogLevel значение info, но для mod_rewrite сделает значение trace5.

Это заменяет директивы ведения журналов для каждого модуля, такие как RewriteLog, которые присутствовали в более ранних версиях сервера.

Обратите внимание, что информация, которую генерируют модули, всегда попадает в лог ошибок, даже если не является по сути ошибкой! Также обратите внимание, что некоторые модули не будут показывать никакой информации, если не установить уровень трассировки в диапазоне от trace1 до trace8.

Также смотрите «Журнал (логи) преобразований mod_rewrite».


Рекомендуется Вам:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *