Короткий ответ: в RHEL 9 и 10, Ubuntu 22.04 и 24.04, Debian 12 и 13, AlmaLinux и Rocky локальные логи собирает systemd-journald, а на удалённый сервер их отправляет rsyslog через модуль omfwd по TCP с очередью на диске. Такая связка закрывает большинство задач централизованного сбора. Syslog-ng выбирают там, где нужна сложная маршрутизация: несколько приёмников, разбор и перезапись полей, десятки фильтров.
Надёжность схемы держится на четырёх настройках: TCP вместо UDP, буфер queue.type="disk" на случай недоступности приёмника, TLS для шифрования и фильтр, который отсекает debug-шум. Логи пропадают почти всегда из-за того, что один из этих пунктов пропущен.
Дальше: сравнение технологий, готовые конфиги rsyslog и syslog-ng, постоянное хранилище journald, права и ротация, чек-лист диагностики потери сообщений. Каждый пример проверяется на стенде за 20-30 минут.
Какую систему логирования выбрать: syslog, rsyslog, syslog-ng или journald
Четыре названия часто используют как синонимы, хотя это разные уровни стека. Путаница в терминологии приводит к тому, что администратор ищет документацию не для того компонента.
Чем syslog отличается от rsyslog и syslog-ng
syslog - это протокол обмена сообщениями. Первый формат зафиксирован в RFC 3164 (2001 год, BSD-строка с приоритетом и меткой времени без года), актуальный - в RFC 5424 (2009 год): структурированные блоки данных SD-ID, точность времени до микросекунд, обязательная кодировка UTF-8, идентификатор сообщения MSGID.
rsyslog и syslog-ng - демоны, которые принимают и отправляют сообщения в обоих форматах и добавляют то, чего в протоколе нет: очереди на диск, TLS, RELP, шаблоны имён файлов, фильтры по десяткам свойств. Rsyslog входит в базовую поставку RHEL, AlmaLinux, Rocky, Fedora, Debian и Ubuntu. Syslog-ng ставят в SUSE Linux Enterprise и openSUSE, часто выбирают в компаниях с большим парком сетевого оборудования, где нужны цепочки маршрутизации. Пакеты есть в репозиториях большинства дистрибутивов, поэтому выбор не привязан к платформе.
Journald: когда systemd-логов достаточно, а когда нет
journald входит в systemd и пишет структурированные записи в бинарный журнал. Каждое сообщение несёт поля _PID, _UID, _GID, _COMM, _SYSTEMD_UNIT, _HOSTNAME, _BOOT_ID, MESSAGE. Для локальной отладки это удобнее текстовых файлов: команда journalctl -u nginx --since "1 hour ago" -p err возвращает только ошибки конкретного сервиса.
Ограничения конкретны. Бинарный формат читается через journalctl или journal-gatewayd. Родной протокол journald не рассчитан на передачу по сети: systemd-journal-upload умеет отправлять журнал на journal-remote, но фильтрация и маршрутизация там беднее, чем в rsyslog. Журнал привязан к systemd, а в контейнерах без systemd он недоступен. Поэтому в схеме с централизацией journald выступает источником, а транспорт выполняет rsyslog или syslog-ng. Как читать журнал, фильтровать по сервису, PID и времени, настраивать хранение и ротацию, разобрано в практическом руководстве по journalctl.
| Критерий | journald | rsyslog | syslog-ng |
|---|---|---|---|
| Формат хранения | бинарный журнал | текстовые файлы, шаблоны | текстовые файлы, шаблоны |
| Поставка по умолчанию | все дистрибутивы с systemd | RHEL, Debian, Ubuntu, Fedora | SUSE, ставится отдельным пакетом |
| Фильтрация | поля и юниты, только локально | property-based фильтры, RainerScript | filter и parser, свой язык конфигурации |
| Передача по сети | journal-upload, ограниченно | TCP, UDP, TLS, RELP | TCP, UDP, TLS, disk-buffer |
| Очередь при сбое сети | нет | queue.type="disk" | disk-buffer() |
| Структурированные поля | есть | через imjournal | через systemd-journal() |
| Порог входа | низкий | средний | выше среднего |
Для типового парка серверов оптимальна связка journald + rsyslog: журнал остаётся локально для отладки, rsyslog отправляет копии по сети. Syslog-ng берут при маршрутизации в несколько приёмников и разборе нестандартных форматов. Rsyslog без journald уместен в контейнерах и системах без systemd. Чистый journald оставляют на одиночных машинах, где централизованный сбор не нужен.
Локальный сбор логов: настройка journald и rsyslog
Удалённая отправка бесполезна, если локально логи не сохраняются. По умолчанию journald в ряде сборок пишет в /run/log/journal, то есть в оперативную память: после перезагрузки записи исчезают.
Включаем persistent storage в journald
Правка /etc/systemd/journald.conf:
[Journal] Storage=persistent SystemMaxUse=500M SystemKeepFree=1G MaxRetentionSec=2week Compress=yes ForwardToSyslog=yes
Storage=persistent создаёт каталог /var/log/journal при первом запуске. Значение auto пишет на диск только если каталог уже существует, и именно это поведение встречается в части сборок. SystemMaxUse=500M ограничивает журнал, SystemKeepFree=1G оставляет свободное место на разделе, чтобы journald не заполнил диск целиком. MaxRetentionSec=2week удаляет записи старше двух недель независимо от размера. Compress=yes сжимает блоки данных, доступ к записям через journalctl остаётся прозрачным.
Применение и проверка:
systemctl restart systemd-journald ls -la /var/log/journal journalctl --disk-usage
Последняя команда выводит строку вида "Archived and active journals take up 128.0M in the file system". Если каталог /var/log/journal пуст или отсутствует, настройка не применилась: проверьте переопределения в /etc/systemd/journald.conf.d/*.conf и вывод systemctl status systemd-journald.
Базовая конфигурация rsyslog
Файл /etc/rsyslog.conf делится на три части. Модули: module(load="imuxsock") читает локальный сокет, module(load="imjournal") читает журнал systemd, module(load="imklog") забирает сообщения ядра. Глобальные параметры: $WorkDirectory /var/spool/rsyslog задаёт каталог для очередей. Правила: селектор facility.severity и действие.
authpriv.* /var/log/auth.log *.info;mail.none;authpriv.none;cron.none /var/log/syslog cron.* /var/log/cron.log
Селектор читается как "facility уровня severity и выше". Запись *.info означает все facility с уровнем info и более важным, mail.none исключает почтовые сообщения. В RHEL и AlmaLinux базовый файл называется /var/log/messages, в Debian и Ubuntu - /var/log/syslog. Свои правила кладут в /etc/rsyslog.d/*.conf, файлы подключаются в алфавитном порядке, поэтому префиксы 10-, 50-, 90- задают приоритет. Перед перезапуском проверяйте синтаксис:
rsyslogd -N1
Команда разбирает конфигурацию и завершается строкой "rsyslogd: End of config validation run. Bye." Ошибки с номером строки появляются выше.
Отправка логов на удалённый сервер: rsyslog и syslog-ng
Транспорт выбирают по двум критериям: гарантия доставки и шифрование. UDP (символ @ в конфиге) не подтверждает приём, при перегрузке сети пакеты пропадают. TCP (символ @@) даёт подтверждение на уровне сегментов, а очередь с сохранением на диск (disk-assisted queue) позволяет пережить недоступность приёмника длиной в часы и сутки. Архитектуру всего конвейера, включая выбор хранилища, разбирает обзор архитектуры централизованного сбора логов.
Сервер-коллектор держите отдельно от продакшена: он принимает трафик со всех хостов и хранит данные, которые нужны при разборе инцидентов. Для этой роли подходит VPS с 2-4 vCPU и диском от 80 ГБ, например в Timeweb Cloud, где диск наращивается независимо от вычислительных ресурсов.
Настройка rsyslog: TCP, TLS и очередь на диске
Файл /etc/rsyslog.d/50-remote.conf на клиенте:
module(load="omfwd")
*.* action(type="omfwd"
target="log.example.com"
port="6514"
protocol="tcp"
tls="on"
tls.caCert="/etc/rsyslog.d/ca.pem"
tls.myCert="/etc/rsyslog.d/client.pem"
tls.myPrivKey="/etc/rsyslog.d/client.key"
tls.authmode="x509/name"
tls.permittedpeer="log.example.com"
queue.type="disk"
queue.filename="remote_queue"
queue.maxdiskspace="1g"
queue.saveonshutdown="on"
action.resumeRetryCount="-1"
action.resumeInterval="30")
Параметры по смыслу:
- target и port: адрес коллектора. Порт 6514 закреплён за syslog over TLS в RFC 5425, без шифрования используют 514.
- protocol="tcp": подтверждение доставки на транспортном уровне.
- tls.*: пути к сертификатам. Режим authmode="x509/name" проверяет имя в сертификате сервера, permittedpeer фиксирует допустимое значение CN или SAN.
- queue.type="disk": сообщения буферизуются в /var/spool/rsyslog, а не в оперативной памяти. queue.maxdiskspace="1g" задаёт предел буфера.
- queue.saveonshutdown="on": очередь сохраняется при остановке демона и читается после запуска. Без этого параметра буфер теряется при перезагрузке.
- action.resumeRetryCount="-1": бесконечные повторные подключения с интервалом 30 секунд.
Короткая форма записи: *.* @@log.example.com:514 для TCP и *.* @log.example.com:514 для UDP. Для продакшена используйте расширенный синтаксис из примера. Перезапуск: systemctl restart rsyslog, проверка конфигурации: rsyslogd -N1.
Настройка syslog-ng: destination и network()
Файл /etc/syslog-ng/conf.d/remote.conf:
destination d_remote {
network("log.example.com" port(6514) transport("tls")
tls(
ca-file("/etc/syslog-ng/ca.pem")
cert-file("/etc/syslog-ng/client.pem")
key-file("/etc/syslog-ng/client.key")
)
disk-buffer(
mem-buf-size(64M)
disk-buf-size(1024M)
reliable(yes)
)
);
};
log {
source(s_src);
destination(d_remote);
};
disk-buffer() создаёт файл буфера в /var/lib/syslog-ng. Опция reliable(yes) сохраняет буфер при перезапуске демона и доступна в syslog-ng 4.2 и новее; на ветке 3.x буфер в памяти теряется при остановке. Проверка конфигурации: syslog-ng -s, перезапуск: systemctl restart syslog-ng.
Разделение логов по источникам на принимающей стороне
На коллекторе rsyslog раскладывает принятые сообщения по каталогам с именами хостов. Конфигурация /etc/rsyslog.d/10-remote.conf:
module(load="imtcp")
input(type="imtcp" port="514")
template(name="RemoteLogs" type="string"
string="/var/log/remote/%hostname%/%programname%.log")
*.* action(type="omfile" dynaFile="RemoteLogs"
fileCreateMode="0640" dirCreateMode="0750"
fileOwner="root" fileGroup="adm")
dynaFile подставляет имя файла из шаблона для каждого сообщения. Значение %hostname% берётся из заголовка syslog, %programname% из тега. Если хост передаёт пустое имя или символ "/" в поле, каталог не создастся и запись уйдёт в ошибку; в таких случаях %hostname% заменяют на %fromhost-ip%. Для приёма по TLS добавьте в imtcp параметры streamDriver="gtls", streamDriverMode="1", streamDriverAuthMode="x509/name" и путь к сертификатам.
В syslog-ng раскладка выполняется через макросы:
destination d_by_host {
file("/var/log/remote/${HOST}/${PROGRAM}.log" create-dirs(yes));
};
Фильтрация логов: отправляем только то, что нужно
Основной объём журналов даёт шум: debug-записи, регулярные задачи cron, проверки healthcheck каждые 5 секунд. Без фильтрации канал и хранилище растут линейно вместе с числом сервисов. Критерии, что действительно стоит отправлять, собраны в статье что логировать, а что нет.
Фильтры в rsyslog: по программе, facility и severity
Property-based фильтры проверяют поля сообщения. Severity кодируется числами: 0 emerg, 1 alert, 2 crit, 3 err, 4 warning, 5 notice, 6 info, 7 debug. Меньшее число означает более высокий приоритет, поэтому условие $syslogseverity <= 4 выбирает warning и всё, что важнее.
if $syslogfacility-text == 'authpriv' then {
action(type="omfwd" target="log.example.com" port="6514"
protocol="tcp" tls="on"
queue.type="disk" queue.filename="auth_queue"
queue.maxdiskspace="512m")
stop
}
if $syslogseverity <= 4 then {
action(type="omfwd" target="log.example.com" port="6514"
protocol="tcp" tls="on"
queue.type="disk" queue.filename="warn_queue")
stop
}
Директива stop прекращает обработку сообщения последующими правилами, а порядок блоков задаёт приоритет: правила читаются сверху вниз. Фильтр по программе выглядит так: if $programname == 'nginx' then { ... }. Комбинация условий: if ($programname == 'sshd') and ($syslogseverity <= 5) then { ... }.
Логи приложений удобнее фильтровать на стороне приложения: чем меньше мусора уходит в syslog, тем дешевле хранение. Для Python-сервисов приёмы буферизации и асинхронной записи разобраны в материале как ускорить логирование в Python без потери детальности.
Фильтры в syslog-ng
filter f_auth { facility(authpriv); };
filter f_warn { level(warn..emerg); };
filter f_nginx { program("nginx"); };
log { source(s_src); filter(f_auth); destination(d_remote); };
log { source(s_src); filter(f_warn); destination(d_remote); };
Запись level(warn..emerg) покрывает диапазон от warning до emergency. Фильтры комбинируются логическими операторами: filter f_auth_warn { facility(authpriv) and level(warn..emerg); };. Слишком узкий фильтр скрывает события, которые нужны при разборе сбоя. Перед отправкой правил на весь парк прогоните их на одном стенде и сравните объём с полным потоком. Отдельно проверяйте, что фильтр не отсекает сообщения о старте сервисов: они помогают восстановить хронологию.
Проверка подключения и диагностика потери сообщений
Проверка занимает меньше минуты, если идти по шагам: отправить тестовое сообщение, найти его на приёмнике, убедиться, что соединение установлено.
Быстрая проверка: доходит ли сообщение
На клиенте:
logger -p local0.err -t deploy-check "test-$(date +%s)"
На коллекторе:
tail -f /var/log/remote/web-01/*.log | grep deploy-check grep deploy-check /var/log/remote/web-01/*.log
Уровень err выбран намеренно: если фильтр отправляет только warning и выше, сообщение с уровнем info не покинет клиент, и вы решите, что сломан транспорт. Соединение проверяют через ss -tnp | grep 6514 и tcpdump -ni eth0 port 6514 -A на приёмнике. Флаг -p в ss показывает процессы и требует root. Пустой вывод tcpdump при работающем клиенте указывает на firewall или неверный адрес.
Диагностика: почему логи теряются
Семь причин покрывают большинство случаев:
- UDP вместо TCP. Пакеты пропадают при перегрузке очереди сокета, и потерь не видно ни в одном логе. Проверка: ss -u -a | grep 514 и повтор tcpdump с фильтром udp port 514.
- Очередь в памяти. Без queue.type="disk" rsyslog держит сообщения в RAM, и при рестарте или нехватке ресурсов буфер исчезает. Проверка: ls -la /var/spool/rsyslog, наличие файлов remote_queue.qi.
- Переполнен диск. Проверка: df -h /var/log /var/spool и journalctl --disk-usage. При заполнении раздела rsyslog останавливает запись и теряет сообщения из очереди.
- Фильтр отсекает нужное. Временный конфиг с *.* в отдельном файле показывает, доходит ли поток без условий.
- SELinux или AppArmor блокирует нестандартный порт. Проверка: ausearch -m avc -ts recent и dmesg | grep -i denied. Для порта 6514 в RHEL: semanage port -a -t syslogd_port_t -p tcp 6514.
- Шаблон на приёмнике даёт неверный путь, например пустой %hostname%. Проверка: тестовое сообщение с явным тегом и просмотр каталога /var/log/remote.
- Расхождение часов. При сдвиге времени больше чем на час сообщения попадают не в тот файл ротации или выпадают из выборки --since. Проверка: timedatectl и chronyc tracking.
Счётчики очередей показывает модуль impstats: module(load="impstats" interval="60" log.syslog="on") публикует размер очереди и число отброшенных сообщений. Для отладки правил запускают rsyslogd -dn (режим debug в foreground) и смотрят, какие фильтры срабатывают. Вывод большой, поэтому применяют на стенде, а не на продакшене.
Отдельная ловушка в imjournal: по умолчанию модуль ограничивает приём значениями Ratelimit.Interval=600 и Ratelimit.Burst=20000, то есть отбрасывает лишние записи при всплеске.
Когда нужно быстро разобрать большую выгрузку, агрегированные фрагменты удобно прогонять через LLM по API. Единый доступ к 200+ моделям (GPT, Gemini, Claude) с оплатой в рублях и без VPN даёт агрегатор AiTunnel. Перед отправкой обезличивайте данные: имена пользователей, IP и токены в URL заменяйте плейсхолдерами.
Права доступа, ротация и защита логов
Логи содержат имена пользователей, внутренние адреса, иногда токены в query string. Три задачи: закрыть чтение для посторонних, не дать журналам занять весь диск, зашифровать трафик между хостами.
Права на файлы и каталоги логов
В Debian и Ubuntu системные логи читает группа adm, в RHEL и производных файлы обычно принадлежат root:root с правами 600. Для каталога /var/log/remote рабочий вариант: владелец root, группа adm, права 750; файлы 640.
chown -R root:adm /var/log/remote
chmod 750 /var/log/remote
find /var/log/remote -type f -exec chmod 640 {} +
Права новых файлов задают прямо в действии rsyslog: fileCreateMode="0640", dirCreateMode="0750", fileOwner="root", fileGroup="adm". Проверка: ls -la /var/log/remote. Специалисту, которому нужен доступ к логам приложений, добавляют группу adm: usermod -aG adm username.
Ротация: logrotate и journald
Файл /etc/logrotate.d/remote-logs:
/var/log/remote/*/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 root adm
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
Параметры: daily и rotate 14 хранят две недели истории, compress сжимает старые файлы, delaycompress оставляет вчерашний файл несжатым на случай, если rsyslog ещё пишет в него, notifempty пропускает пустые файлы. Путь к rsyslog-rotate отличается: в Debian и Ubuntu это /usr/lib/rsyslog/rsyslog-rotate, в RHEL, AlmaLinux и Rocky - /usr/libexec/rsyslog/rsyslog-rotate. Скрипт посылает демону сигнал, и тот переоткрывает файлы. Если postrotate не срабатывает, файлы продолжают расти вопреки ротации. Проверка: logrotate -d /etc/logrotate.d/remote-logs (dry run) и logrotate -f /etc/logrotate.d/remote-logs (принудительный запуск).
Для journald лимиты прописывают в /etc/systemd/journald.conf: SystemMaxUse=1G и MaxRetentionSec=2week. Ручная очистка: journalctl --vacuum-size=500M или journalctl --vacuum-time=7d. Команды удаляют данные сразу, поэтому сначала смотрят текущий объём через journalctl --disk-usage.
Шифрование передачи: TLS и RELP
Без TLS syslog идёт открытым текстом, включая содержимое сообщений. Шифрование в rsyslog обеспечивает драйвер gtls из пакета rsyslog-gnutls, порт 6514 закреплён за syslog over TLS в RFC 5425. Параметр tls.authmode="x509/name" вместе с tls.permittedpeer защищает от подмены сервера: клиент сверяет имя в сертификате. Сертификаты выпускают внутренним PKI или генерируют самоподписанные для тестового контура.
RELP (Reliable Event Logging Protocol) добавляет прикладные подтверждения доставки поверх TCP и работает в rsyslog через модули omrelp и imrelp (пакет rsyslog-relp), стандартный порт 20514. Приёмник подтверждает каждое сообщение, поэтому потери при обрыве связи видны сразу. TLS и RELP повышают нагрузку на CPU: на профиле в 10 000 сообщений в секунду включение шифрования заметно и требует теста с реальным трафиком.
Связка journald и rsyslog: как избежать дублирования и потерь
Journald и rsyslog взаимодействуют двумя способами. Параметр ForwardToSyslog=yes в journald.conf отправляет записи в сокет /run/systemd/journal/syslog, откуда их читает модуль imuxsock. Модуль imjournal читает бинарный журнал /var/log/journal напрямую и сохраняет структурированные поля. Если включены оба пути, rsyslog получает каждое сообщение дважды, и в централизованном хранилище появляются дубли.
ForwardToSyslog и imjournal: что выбрать
Схема с imuxsock проще: сообщения приходят в текстовом формате syslog, фильтры работают по facility и severity. В RHEL 8, 9 и 10 в /etc/rsyslog.conf включён imjournal с файлом состояния, а локальный сокет у imuxsock отключён параметром SysSock.Use="off". В Debian и Ubuntu по умолчанию ForwardToSyslog=yes, и текст читает imuxsock.
Когда нужны поля _SYSTEMD_UNIT, _PID и _COMM, выбирайте imjournal:
module(load="imjournal"
StateFile="imjournal.state"
IgnorePreviousBoot="off"
PersistStateInterval="1000")
StateFile хранит позицию чтения, чтобы после перезапуска rsyslog не перечитывал журнал с начала. IgnorePreviousBoot="off" забирает записи прошлых загрузок, при значении on пропускает их. PersistStateInterval="1000" сохраняет позицию каждые 1000 сообщений: меньшее значение надёжнее и создаёт больше записей на диск. Поля доступны в шаблонах как $!_SYSTEMD_UNIT, $!_PID, $!_COMM, а всё дерево свойств выводится в JSON одной строкой:
template(name="JsonLine" type="string" string="$!all-json")
Отдельная ловушка: journald ограничивает поток на 10 000 сообщений за 30 секунд (RateLimitBurst и RateLimitIntervalSec в journald.conf). Активный сервис, который печатает чаще, получает в журнале пометку "Suppressed N messages", и часть событий не доходит до коллектора. Порог поднимают глобально или отключают лимит для конкретной службы через LogRateLimitIntervalSec=0 в unit-файле.
Что выбрать: один источник и один транспорт. Схема imjournal + rsyslog с очередью на диске даёт структурированные поля и надёжную отправку, а дальше данные удобно выводить в Grafana и Elasticsearch, как описано в руководстве по системному логированию. Проверка, что путь один:
grep -r "imjournal\|imuxsock\|ForwardToSyslog" /etc/rsyslog.conf /etc/rsyslog.d/ /etc/systemd/journald.conf journalctl -u rsyslog -n 20
Если в выводе есть оба модуля при включённом ForwardToSyslog, отключите imuxsock строкой SysSock.Use="off" либо выставьте ForwardToSyslog=no. Дублирование замечают по одинаковым записям с разницей в доли секунды: они удваивают объём хранилища и мешают считать статистику.
Минимальный рабочий набор: Storage=persistent в journald, один путь journald - rsyslog, omfwd с TCP и TLS, очередь queue.type="disk" вместе с saveonshutdown, фильтр warning+ и отдельное правило для authpriv, logrotate на 14 дней, права 640 на файлы. Эти настройки закрывают типовые требования по надёжности и безопасности логов.