Уровни логирования в Syslog: от emerg до debug - настройка и маршрутизация | AdminWiki

Уровни логирования в Syslog: от emerg до debug - настройка и маршрутизация

01 октября 2026 13 мин. чтения
Содержание статьи

Что такое уровни логирования в Syslog и зачем они нужны

Syslog описывает формат системных сообщений в RFC 5424, и severity в нём - числовой код от 0 до 7. Ноль соответствует emerg, семёрка - debug. Уровень выставляет то приложение или демон, которое формирует сообщение, а сервер логирования только читает приоритет из заголовка и раскладывает записи по правилам. Повысить или понизить severity на стороне приёмника нельзя, можно лишь отфильтровать сообщение или перенаправить его в другой файл.

Ценность шкалы в том, что она даёт единый язык для фильтрации и маршрутизации. Одна строка конфига отправляет все ошибки в отдельный файл, оставляет отладку на хосте и пересылает предупреждения на центральный сервер. Без уровней пришлось бы разбирать текст сообщений регулярками, а формулировки меняются между версиями сервисов. Фильтр по числовому коду стабилен и не зависит от языка, на котором написано приложение.

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

Шкала severity: emerg, alert, crit, err, warning, notice, info, debug

КодУровеньЧто означаетТипичный пример
0emergСистема неработоспособнаПаника ядра, потеря корневой файловой системы
1alertНужно немедленное вмешательствоВышел из строя диск в RAID-массиве
2critКритическое состояниеПриложение не может подключиться к базе данных
3errОшибка выполненияНе удалось открыть конфиг, отклонён запрос
4warningПредупреждениеРаздел заполнен на 90%, истекает сертификат
5noticeНормальное, но значимое событиеПерезапуск сервиса, смена пользователя
6infoИнформационное сообщениеСтарт сервиса, успешный вход
7debugОтладочные данныеПошаговые логи, тексты SQL-запросов

Ключевая логика, на которой строятся все селекторы: чем меньше число, тем выше приоритет. Фильтр с порогом err пропускает коды 3, 2, 1 и 0. Это не «только ошибки», а «ошибки и всё, что серьёзнее». Разница между соседними уровнями в том, кто должен реагировать: emerg и alert требуют человека немедленно, crit и err означают сбой функции, warning - сигнал к проверке, notice и info фиксируют нормальный ход событий, debug нужен только при разборе инцидента.

По RFC 5424 значения severity обязаны находиться в диапазоне от 0 до 7 включительно, а значения facility - от 0 до 23 включительно. Итоговый приоритет сообщения (PRIVAL) вычисляется как facility × 8 + severity. Именно поэтому числовой код уровня и источник сообщения удобно хранить и сравнивать как единое число.

Facility и severity: как они работают вместе

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

КодFacilityИсточник
0kernЯдро
1userПользовательские процессы
2mailПочтовая подсистема
3daemonСистемные демоны
4authАутентификация
5syslogСам демон логирования
6lprПечать
7newsПодсистема сетевых новостей (NNTP)
8uucpUUCP
9cronПланировщик
10authprivПриватная аутентификация
11ftpFTP
15clock daemonДемон времени
16-23local0-local7Свободные метки для своих приложений

В rsyslog пара записывается как selector: authpriv.* или *.err. В syslog-ng facility и уровень задаются отдельными функциями filter: facility(auth, authpriv) и level(warning..emerg). Пример комбинации: логи аутентификации от warning и выше - это authpriv.warning в rsyslog и filter с двумя условиями в syslog-ng.

Диапазон local0-local7 - стандартный способ пометить кастомные приложения, чтобы отделить их от системных демонов. Приложение указывает facility в своей конфигурации или в параметре syslog-драйвера. Контейнеры передают сообщения так же: драйвер syslog в Docker добавляет теги, а уровень задаёт само приложение через собственный log_level. Если приложение пишет всё на info, фильтр по severity на сервере не сможет отделить шум, потому что уровень уже потерян.

Маршрутизация логов по уровням в rsyslog

rsyslog читает основной файл /etc/rsyslog.conf и подключает всё из /etc/rsyslog.d/*.conf. Маршрутизация строится на селекторах вида facility.severity либо на условиях RainerScript. Правила обрабатываются сверху вниз, а директива stop прерывает обработку сообщения.

Селекторы facility.severity: синтаксис и примеры

Селектор состоит из facility, точки и severity. Звёздочка означает «любой». В официальной документации rsyslog facility перечисляется ключевыми словами: auth, authpriv, cron, daemon, kern, lpr, mail, mark, news, security (то же, что auth), syslog, user, uucp и local0-local7. Priority перечисляется в возрастающем порядке: debug, info, notice, warning, warn (то же, что warning), err, error (то же, что err), crit, alert, emerg, panic (то же, что emerg); ключевые слова error, warn и panic считаются устаревшими.

  • *.err - все сообщения уровня err и выше, то есть коды 3, 2, 1 и 0;
  • authpriv.* - всё, что пишет подсистема аутентификации, независимо от уровня;
  • mail.info - почта от info и выше;
  • *.=warning - только warning, без crit и err;
  • *.!=debug - всё, кроме отладки;
  • auth,authpriv.* - два facility в одном селекторе через запятую.

Читайте селектор как «этот уровень и всё, что важнее». Запись *.err не включает info и debug, зато включает crit, alert и emerg, потому что их числовые коды меньше порога. Если нужен строго один уровень, ставьте знак равенства: *.=err даст только ошибки кода 3 и не пропустит сообщение о падении базы данных с уровнем crit. Расширение с «=» перед priority - это синтаксическое расширение rsyslog поверх исходного синтаксиса BSD, оно и позволяет указать единственный уровень вместо «этот и все более важные».

Условия RainerScript: if $syslogseverity и $syslogfacility

Условия гибче селекторов: они позволяют сравнивать числовые коды и текстовые имена источников. Property-based фильтры rsyslog работают со свойствами сообщения, включая $syslogfacility-text, и поддерживают булевы операции.

if $syslogseverity <= 3 then {
    action(type="omfile" file="/var/log/errors.log")
}

if $syslogfacility-text == "authpriv" and $syslogseverity <= 4 then {
    action(type="omfile" file="/var/log/auth-warnings.log")
}

$syslogseverity хранит числовой код от 0 до 7, поэтому условие <= 3 означает err и выше. $syslogfacility-text отдаёт имя facility, $syslogfacility - его номер. Блоки выполняются сверху вниз, а stop внутри блока не даёт сообщению дойти до следующих правил. Официальный пример такого подхода выглядит так: if $syslogfacility-text == 'local0' and $msg startswith 'DEVNAME' and ($msg contains 'error1' or $msg contains 'error0') then /var/log/somelog.

Готовый конфиг: разделение логов по уровням

# /etc/rsyslog.d/10-levels.conf

# Аутентификация: пишем полностью, включая crit и err
authpriv.*              action(type="omfile" file="/var/log/auth.log")

# Критичные события: emerg, alert, crit
*.emerg;*.alert;*.crit  action(type="omfile" file="/var/log/critical.log")

# Только ошибки уровня err
*.=err                  action(type="omfile" file="/var/log/errors.log")

# Отладка в отдельный файл
*.=debug                action(type="omfile" file="/var/log/debug.log")

# Общий поток от info и выше
*.info                  action(type="omfile" file="/var/log/messages.log")

# Свои приложения на local0 и local1
local0.*;local1.*       action(type="omfile" file="/var/log/apps.log")

Без stop сообщение уровня crit попадёт сразу в critical.log и в messages.log. Иногда дублирование удобно, иногда мешает считать события. Чтобы запись обработалась один раз, завершите нужный блок директивой stop:

if $syslogseverity <= 2 then {
    action(type="omfile" file="/var/log/critical.log")
    stop
}

Проверяйте синтаксис командой rsyslogd -N1 и только после неё перезапускайте сервис. Новые файлы нужно добавить в logrotate, иначе диск заполнится быстрее, чем вы заметите:

/var/log/debug.log {
    daily
    rotate 3
    compress
    missingok
    notifempty
}

Маршрутизация логов по уровням в syslog-ng

Конфигурация syslog-ng строится из четырёх типов блоков: source, filter, destination и log. Один source можно использовать в нескольких log-блоках, а фильтры комбинируются операторами and, or и not. Файл по умолчанию - /etc/syslog-ng/syslog-ng.conf.

Фильтры level() и facility(): синтаксис и примеры

Фильтр facility() принимает имя facility, числовой код facility или диапазон имён facility. Коды 0-23 предопределены и могут указываться по обычному имени, коды выше 24 являются пользовательскими. Нотация диапазона поддерживается только для именованных значений, а не для числовых.

  • filter f_err { level(err..emerg); }; - диапазон от err до emerg;
  • filter f_auth { facility(auth, authpriv); }; - два источника через запятую;
  • filter f_not_debug { not level(debug); }; - всё, кроме отладки;
  • filter f_warning_only { level(warning); }; - строго один уровень.

Функция level() принимает и числовые коды, но имена читаемее и меньше подвержены опечаткам. Диапазон записывается двумя точками: level(err..emerg) охватывает коды 3, 2, 1 и 0. В официальной документации и примерах ArchWiki тот же фильтр по уровню встречается и в форме severity(), например severity(info) или severity(info..warn), а комбинированный фильтр выглядит как level(info..warn) and not facility(cron, auth, authpriv, mail, news). В строке @version указывайте версию своего syslog-ng, иначе демон применит режим совместимости со старым синтаксисом.

Готовый конфиг: разделение логов по уровням

@version: 4.0
@include "scl.conf"

source s_sys {
    system();
    internal();
};

destination d_auth  { file("/var/log/auth.log"); };
destination d_err   { file("/var/log/errors.log"); };
destination d_debug { file("/var/log/debug.log"); };
destination d_main  { file("/var/log/messages.log"); };

filter f_auth  { facility(auth, authpriv); };
filter f_err   { level(err..emerg); };
filter f_debug { level(debug); };

log { source(s_sys); filter(f_auth);  destination(d_auth); };
log { source(s_sys); filter(f_err);   destination(d_err); };
log { source(s_sys); filter(f_debug); destination(d_debug); };
log { source(s_sys); filter { not level(debug); }; destination(d_main); };

Каждый log-блок независим, поэтому одно и то же сообщение легко попадает в несколько файлов. Если нужна взаимоисключающая раскладка, добавляйте в фильтры not: например, filter { not level(debug) and not level(err..emerg); } для общего потока. В примерах документации фильтр отладки часто исключает шумные источники: filter f_debug { not facility(auth, authpriv, news, mail); }.

Отправка логов на удалённый syslog-сервер

Оба демона умеют пересылать сообщения по UDP, TCP и TLS. Для продакшена выбирайте TCP или TLS: UDP не подтверждает доставку и теряет пакеты при перегрузке сети, а для критичных событий и журналов аудита потеря записи означает дыру в расследовании инцидента.

По портам картина такая: syslog использует UDP-порт 514 по умолчанию, а TCP-порт 6514 закреплён как порт по умолчанию для syslog over TLS (RFC 5425, ключевое слово syslog-tls в диапазоне Registered Port Numbers). При этом TCP 514 официально принадлежит службе rsh, и использование его для syslog - широко распространённая практика, а не назначение IANA.

rsyslog: omfwd, TCP/UDP и TLS

Модуль omfwd пересылает логи на удалённые системы по UDP, TCP или TLS. Драйвер потока выбирается параметром StreamDriver.Name: по умолчанию это plain tcp, также доступны «ossl» или «gtls» для TLS-шифрования. Режим драйвера задаётся параметром StreamDriver.Mode.

# TCP с очередью на диске: сообщения переживут перезапуск сервиса
action(
    type="omfwd"
    target="log.example.com"
    port="514"
    protocol="tcp"
    template="RSYSLOG_ForwardFormat"
    queue.type="linkedList"
    queue.filename="fwd_queue"
    queue.saveOnShutdown="on"
    action.resumeRetryCount="-1"
)

# TLS: тот же модуль плюс драйвер потока
action(
    type="omfwd"
    target="log.example.com"
    port="6514"
    protocol="tcp"
    template="RSYSLOG_ForwardFormat"
    streamDriver="gtls"
    streamDriverMode="1"
    streamDriverAuthMode="x509/name"
    streamDriverPermittedPeers="log.example.com"
)

Шаблон RSYSLOG_ForwardFormat сохраняет hostname и timestamp, поэтому на центральном сервере видно, какой хост прислал запись. Очередь на диске защищает от потери при обрыве связи: параметр queue.saveonshutdown="on" сохраняет очередь при остановке демона и читает её после запуска, а без него буфер теряется при перезагрузке. Параметр action.resumeRetryCount="-1" означает бесконечные повторные подключения с интервалом 30 секунд. Как устроена такая очередь и как её проверить, разбирали в материале о настройке сбора логов и отправке на удалённый сервер.

syslog-ng: network() и syslog()

destination d_remote {
    network("log.example.com" port(514) transport("tcp"));
};

destination d_remote_tls {
    syslog("log.example.com" port(6514) transport("tls")
        tls(peer-verify(required-trusted) ca-dir("/etc/ssl/certs")));
};

log { source(s_sys); filter { level(warning..emerg); }; destination(d_remote); };
log { source(s_sys); filter { facility(authpriv); };      destination(d_remote_tls); };

Драйвер syslog() рассчитан на RFC 5424 и умеет то, чего нет у универсального network(): строгий формат, метку времени с часовым поясом, работу с TLS и взаимную проверку сертификатов. Фильтр по уровню ставьте в log-блоке перед destination, тогда на удалённый сервер уйдёт только нужный поток.

Что отправлять на удалённый сервер, а что оставить локально

Рабочая схема: на центральный сервер уходят warning и выше, а info и debug остаются на хосте или включаются точечно. Это снижает трафик и нагрузку на коллектор в разы, потому что основной объём записей даёт именно информационный поток.

Исключение одно и оно важное: authpriv централизуйте целиком, без ограничения по уровню. Локальные журналы аутентификации исчезают вместе с компрометированным хостом, а записи о неудачных входах нужны именно тогда, когда машина уже под контролем атакующего. Схему защищённой передачи таких журналов с TLS описывали в руководстве по сбору логов аудита через rsyslog и auditd.

Типичные ошибки при настройке уровней и фильтров

Ошибка 1: неверное направление шкалы severity

Самая частая причина пропавших инцидентов. Фильтр *.err не исключает crit и emerg, а включает их. Обратная ситуация опаснее: администратор пишет *.=err, ожидая увидеть все проблемы, и теряет сообщения уровня crit о падении базы. Проверка занимает секунду: отправьте тестовое сообщение logger -p user.crit "test crit" и убедитесь, что оно оказалось в нужном файле.

Ошибка 2: debug на проде и переполнение диска

Отладка на продакшене генерирует объём в десятки раз больше обычного потока, ускоряет износ диска и добавляет нагрузку на сервис. Включайте debug точечно: отдельный фильтр, отдельный файл, короткий срок хранения и обязательный logrotate.

if $syslogseverity == 7 then {
    action(type="omfile" file="/var/log/debug.log")
    stop
}

Директива stop в этом блоке не даёт отладочным записям попасть в общий журнал. Если приложение умеет менять уровень на лету, включайте debug через его собственный log_level, а не через правку конфига демона: так вы отключите шум одним запросом к API.

Ошибка 3: порядок правил и потеря сообщений

В rsyslog правила читаются сверху вниз, и stop прерывает обработку. Ранний stop отрезает сообщение от всех последующих файлов. Ставьте его после тех правил, которые должны увидеть запись, и проверяйте, не перекрывает ли общее правило специфичное.

# Сначала специфичное правило для аутентификации
authpriv.*  action(type="omfile" file="/var/log/auth.log")

# Затем критичное и stop
authpriv.crit  action(type="omfile" file="/var/log/auth-critical.log")

В syslog-ng блоки независимы, поэтому потеря сообщений случается по другой причине: пересекающиеся фильтры дают дубли, а их отсутствие в каком-то блоке оставляет часть записей без адресата.

Ошибка 4: отсутствие проверки конфига перед перезапуском

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

Проверка и отладка настроек логирования

Проверка синтаксиса и перезапуск сервиса

rsyslogd -N1
syslog-ng -s
systemctl restart rsyslog
systemctl restart syslog-ng

Команда rsyslogd -N1 разбирает конфигурацию и при успехе завершается строкой «rsyslogd: End of config validation run. Bye.». Успешная проверка синтаксиса не гарантирует логическую правильность: демон не знает, что вы ожидали увидеть crit в файле errors.log. После перезапуска смотрите journalctl -u rsyslog -n 50 и состояние сервиса. Подробный разбор системного логирования, journald и сборки дашбордов есть в отдельном руководстве по системному логированию в Linux.

Тестовая отправка и подтверждение доставки

logger -p user.err "test err"
logger -p authpriv.warning "test auth"
logger -p local0.debug "test debug"

tail -f /var/log/errors.log
ss -tlnp | grep 514
tcpdump -i any port 514 -A

Порядок действий простой: отправить сообщение нужного уровня, посмотреть локальный файл, затем проверить сеть. На удалённой стороне подтверждайте доставку через tail по целевому файлу. Для порта 6514 с TLS tcpdump покажет только зашифрованные байты, поэтому единственный надёжный способ проверки - запись в файле коллектора.

Отладку самого демона включайте через его параметры, а не через приложения: для rsyslog это директива с уровнем отладки в отдельном конфиге, для syslog-ng - ключ запуска с повышенной детализацией. Так вы не зальёте прод отладочными записями со всех сервисов сразу.

Чек-лист перед применением конфига на проде

  • Сохраните копию текущего конфига: cp /etc/rsyslog.conf /etc/rsyslog.conf.bak.
  • Проверьте синтаксис: rsyslogd -N1 или syslog-ng -s.
  • Убедитесь, что crit и выше не отбрасываются ни одним фильтром и попадают в файл или на удалённый сервер.
  • Проверьте, что debug не пишется в общий журнал и лежит в отдельном файле.
  • Добавьте все новые файлы в logrotate с ограничением по количеству копий.
  • Отправьте тестовые сообщения через logger на каждый уровень и проверьте их место.
  • Подтвердите доставку на коллектор: tail по целевому файлу, затем проверка сети через ss и tcpdump.
  • Убедитесь, что authpriv уходит централизованно, без ограничения по уровню.
  • Проверьте порядок правил: специфичные условия выше, stop после них.
  • Заранее решите, где хранить debug и как быстро его удалять, чтобы не переполнить диск.

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

Поделиться: