Погодин Евгений — ИТ Заметки
🐧Linux Обновлено 04.11.2026

Linux для админа Windows 17. Журналы: journald, rsyslog и logrotate

Note

Материал сверен с официальной документацией (Ubuntu Server, man-страницы и документация проектов; ссылки — в конце статьи). Примеры вывода — иллюстрации: на вашем сервере значения и формат могут отличаться. Перед работой на боевом сервере проверьте команды на тестовой машине.

В Windows причину сбоя ищут в Просмотре событий: журналы «Приложение», «Система» и «Безопасность», фильтры по уровню и времени, Get-WinEvent для скриптов. В Ubuntu Server задача та же, но журналы устроены иначе: часть событий хранит двоичный журнал службы systemd-journald, часть лежит в обычных текстовых файлах в /var/log, а раскладывает их по файлам демон rsyslog. В этой статье вы:

  • разберётесь, чем journald отличается от rsyslog и какие файлы лежат в /var/log;
  • научитесь находить причину сбоя фильтрами journalctl, включая разбор неудачных входов по SSH;
  • настроите ротацию собственного лога через logrotate и ограничите размер журнала;
  • узнаете, кто может читать логи, что в них нельзя оставлять и как пересылать их на другой сервер.
Задача Windows Ubuntu Server
Читать события Просмотр событий, Get-WinEvent journalctl, текстовые файлы в /var/log
События за период фильтр «Дата и время», StartTime journalctl --since … --until …
Только ошибки фильтр «Уровень» journalctl -p err
Входы и повышение прав журнал «Безопасность» /var/log/auth.log, journalctl -u ssh
Размер и срок хранения свойства журнала SystemMaxUse= в journald, logrotate
Сбор событий на отдельном сервере Windows Event Forwarding (WEF) пересылка средствами rsyslog

Что нужно знать заранее

Note

Для Ubuntu 24.04 LTS (systemd 255); в 26.04 LTS пакеты новее — проверьте apt policy rsyslog logrotate и документацию выпуска. Файлы с правилами rsyslog в пакетах обоих выпусков совпадают. Основное замеченное отличие — настройка таймера logrotate.timer (см. ниже). Кроме того, в 26.04 LTS постоянное хранение журнала может быть включено по умолчанию: проверьте ls -d /var/log/journal.

Warning

Практика создаёт службу, файлы в /var/log и правила rsyslog, поэтому выполняйте её на тестовой машине и в конце сделайте уборку. Адрес 192.168.10.21 в примере пересылки учебный: подставьте адрес своего сервера журналов.

Два слоя: journald и rsyslog

journald (служба systemd-journald) собирает стандартный вывод и ошибки служб, сообщения ядра, обращения программ к syslog() и записи аудита. Он хранит их в двоичном индексированном журнале вместе с метаданными: из какого юнита пришла запись, какой у неё приоритет, какой процесс её написал. Поэтому записи можно отбирать по полям, а не искать текст. Читают журнал командой journalctl.

rsyslog — классический демон syslog (протокол и формат, на которых десятилетиями строились журналы Unix). Он принимает сообщения и по правилам раскладывает их в текстовые файлы. У каждого сообщения есть facility (источник: auth, authpriv, kern, mail, cron, daemon, user, local0–local7) и priority (важность по возрастанию: debug, info, notice, warning, err, crit, alert, emerg).

В Ubuntu работают оба. Пакет systemd ставит файл /usr/lib/systemd/journald.conf.d/syslog.conf с настройкой ForwardToSyslog=yes, поэтому journald передаёт копию сообщений rsyslog, и одно событие видно и в journalctl, и в /var/log/syslog. Итоговые настройки journald со всеми дополнениями покажет systemd-analyze cat-config systemd/journald.conf.

ядро, службы, программы
        |
 systemd-journald --> /var/log/journal   (двоичный журнал, journalctl)
        |
        +-- копия --> rsyslog --> /var/log/syslog, auth.log, kern.log ...

Сообщения ядра rsyslog читает и сам, модулем imklog, поэтому схема упрощённая. rsyslog в Ubuntu обычно установлен: проверьте systemctl status rsyslog.

Где лежат журналы

Путь Что в нём Кто пишет
/var/log/syslog почти все сообщения, кроме auth и authpriv rsyslog
/var/log/auth.log входы, sudo, смена пользователей (auth, authpriv) rsyslog
/var/log/kern.log сообщения ядра rsyslog
/var/log/mail.log, mail.err почтовая подсистема, если она есть rsyslog
/var/log/dpkg.log, /var/log/apt/ установка и удаление пакетов dpkg, apt
/var/log/nginx/ access.log, error.log nginx
/var/log/journal/ двоичный журнал journald

Читают текстовые файлы привычными less, tail -f и grep, а сжатые архивы (*.gz) — zless и zgrep. Контейнеры Docker пишут свои журналы отдельно, см. статью про Docker.

journalctl: углубляем

Опции -u, -b, -p и -f вы уже знаете. Вот что чаще всего нужно при расследовании:

sudo journalctl -F _SYSTEMD_UNIT
sudo journalctl -u ssh --since today
sudo journalctl -b -p err
sudo journalctl -b -1 -p warning..err
sudo journalctl -k -b -1
sudo journalctl -t sudo --since "1 hour ago"
sudo journalctl -u nginx -o short-iso --utc -n 20
sudo journalctl -n 1 -o verbose
  • -F _SYSTEMD_UNIT перечисляет юниты, от которых есть записи: удобно, если вы не помните имя.
  • -u ssh показывает и сообщения самой службы, и сообщения systemd о её запуске и остановке. В Ubuntu служба SSH называется ssh.
  • -p err отбирает записи этого уровня и более важных (err, crit, alert, emerg); диапазон задают так: -p warning..err.
  • -b -1 — предыдущая загрузка, то есть «что было перед аварийной перезагрузкой» (-k -b -1 — только сообщения ядра той загрузки). Для этого журнал должен храниться на диске (см. статью про службы); список загрузок покажет --list-boots.
  • -t sudo отбирает записи по метке программы (SYSLOG_IDENTIFIER).
  • -o short-iso --utc печатает время в формате ISO 8601 в UTC: удобно сверять с другими серверами и с журналами Windows.
  • -o verbose выводит все поля записи (_SYSTEMD_UNIT, PRIORITY, SYSLOG_IDENTIFIER, _PID и другие). Любое поле работает как фильтр: journalctl _SYSTEMD_UNIT=ssh.service _PID=<номер>. Условия для разных полей объединяются по «И», для одного поля — по «ИЛИ».

Поиск по тексту — опция -g: это регулярное выражение, и если шаблон целиком в нижнем регистре, регистр не учитывается.

Есть ловушка с уровнями. Строки, которые служба печатает в стандартный вывод, получают уровень по умолчанию, и -p err их не покажет. Программа может задать уровень префиксом в начале строки: <3> означает err, и systemd по умолчанию разбирает такие префиксы.

Разбор неудачных входов по SSH

sshd пишет с facility AUTH и уровнем INFO (значения по умолчанию), поэтому записи есть и в журнале службы, и в /var/log/auth.log:

sudo journalctl -u ssh --since today -g 'Failed|Invalid user'
sudo grep -E 'Failed|Invalid user' /var/log/auth.log | tail -n 20

Точный текст сообщений зависит от версии OpenSSH, поэтому сначала посмотрите, как выглядят ваши записи. Это диагностика, а не защита: защищают ключи и отключённый вход по паролю (статья про SSH) и ограничение доступа в ufw.

Размер журнала

Постоянное хранение, SystemMaxUse= и предупреждение о том, что --vacuum-* удаляет записи безвозвратно, описаны в статье про службы. Добавим две детали. Во-первых, вакуум удаляет только архивные файлы журнала; чтобы он охватил и активные, объедините его с ротацией: sudo journalctl --rotate --vacuum-time=2weeks. Во-вторых, помимо размера срок хранения ограничивает MaxRetentionSec= (по умолчанию выключен). Помните и про ограничение частоты: journald отбрасывает сообщения «шумной» службы сверх 10000 за 30 секунд (RateLimitBurst=) и пишет о числе отброшенных в журнал.

rsyslog: правила и каталог rsyslog.d

Главный файл — /etc/rsyslog.conf: в нём подключаются модули (imuxsock для локальных сообщений, imklog для ядра), задаются владелец и права новых файлов (syslog:adm, режим 0640) и подключается всё из /etc/rsyslog.d/*.conf. Стандартные правила Ubuntu лежат в /etc/rsyslog.d/50-default.conf. Своё кладите в отдельный файл с числовым префиксом, как у 50-default.conf, а не правьте чужой.

Правило состоит из селектора facility.priority и действия. Вот ключевые строки из стандартного файла:

auth,authpriv.*              /var/log/auth.log
*.*;auth,authpriv.none       -/var/log/syslog
kern.*                       -/var/log/kern.log
*.emerg                      :omusrmsg:*

Правила читаются так. * значит «любой», none исключает facility, через запятую перечисляют несколько facility, через точку с запятой — несколько селекторов. Приоритет в селекторе означает «этот и более важные»; =err выбирает только err, а ! исключает. Минус перед путём — историческая пометка «не синхронизировать после каждой строки»; сейчас это и так поведение по умолчанию. Последняя строка рассылает аварийные сообщения всем вошедшим пользователям. Проверить правило без события поможет утилита logger: она отправляет сообщение в системный журнал (-p facility.priority задаёт источник и важность, -t — метку записи).

Перед перезапуском проверяйте конфигурацию командой sudo rsyslogd -N1: она только разбирает файлы и сообщает об ошибках. Применяется конфигурация перезапуском: sudo systemctl restart rsyslog. И ещё одно ограничение Ubuntu: rsyslog работает под профилем AppArmor (механизм ядра, ограничивающий программы профилями; подробнее в статье про Docker), который разрешает писать в /var/log/**. Если правило пишет в другой каталог, а файла нет, ищите в dmesg отказы apparmor="DENIED" и дополнение профиля в /etc/apparmor.d/rsyslog.d/ (описано в README пакета), а не отключайте AppArmor.

logrotate: чтобы диск не переполнился

Текстовый журнал растёт, пока его не ротируют. logrotate переименовывает файл (syslog → syslog.1), создаёт новый, сжимает старые копии и удаляет самые старые. Правила лежат в /etc/logrotate.conf и в файлах каталога /etc/logrotate.d/, которые пакеты добавляют сами. Общий файл в Ubuntu содержит такие строки (комментарии убраны):

weekly
su root adm
rotate 4
create
include /etc/logrotate.d

Эти настройки действуют и на файлы из /etc/logrotate.d, если в них не сказано иначе. Блок для конкретного журнала в /etc/logrotate.d/ описывает путь (можно с маской) и директивы в фигурных скобках. Основные директивы:

Директива Что делает
daily, weekly, monthly как часто ротировать
size 100M, maxsize 100M ротировать по размеру (maxsize — и раньше срока)
rotate 4 сколько старых копий хранить; лишние удаляются
compress, delaycompress сжимать gzip; delaycompress откладывает сжатие предыдущей копии до следующего цикла
missingok, notifempty не считать ошибкой отсутствие файла; не ротировать пустой
create 0640 syslog adm создать новый файл с такими режимом, владельцем и группой
su root adm от чьего имени ротировать
postrotate … endscript команды после ротации

Зачем postrotate. Демон держит журнал открытым. После переименования он продолжит писать в syslog.1, пока не откроет файл заново. Поэтому в правиле для файлов rsyslog стоит вызов /usr/lib/rsyslog/rsyslog-rotate, который посылает службе сигнал HUP («обрыв терминала», о сигналах — в статье про процессы); по нему rsyslog закрывает файлы и открывает их заново. Для программы, которая не умеет переоткрывать файл, есть директива copytruncate (скопировать файл и обнулить оригинал), но между копированием и обнулением часть записей может потеряться.

Как запускается. Пакет logrotate приносит таймер logrotate.timer (раз в сутки, с допустимым опозданием до часа, с догоном пропущенных запусков) и службу logrotate.service, которая выполняет /usr/sbin/logrotate /etc/logrotate.conf. Старое задание /etc/cron.daily/logrotate пропускается, если работает systemd. В 26.04 LTS вместо AccuracySec=1h в таймере стоит RandomizedDelaySec=1h: и там и там запуск может сдвинуться не больше чем на час после полуночи, но механизм разный. У AccuracySec= положение в этом окне постоянное для узла, а у RandomizedDelaySec= задержка случайная и выбирается перед каждым запуском. Проверьте: systemctl list-timers logrotate.timer и journalctl -u logrotate.service. Состояние (когда что ротировалось) хранится в /var/lib/logrotate/status. Из-за ежедневного запуска size тоже проверяется раз в сутки, а hourly без более частого запуска бесполезно.

Проверка без последствий — опция -d (debug): ничего не меняется, печатаются только сообщения. Опция -f принуждает к ротации, даже если срок не подошёл, но пустой файл при notifempty не ротируется и с ней. Осторожнее с масками: * захватит и уже ротированные файлы, пишите *.log. Файлы настроек не должны быть доступны на запись группе и остальным.

Права на логи и конфиденциальность

Файлы syslog, auth.log, kern.log принадлежат пользователю syslog и группе adm, режим 0640: читать их могут root и члены группы adm. Участники adm (и systemd-journal) читают и весь журнал journald; без членства в них, и без sudo, пользователь видит только свои записи. Отсюда практические правила:

  • не делайте логи читаемыми для всех (chmod 644): добавьте нужного администратора в группу, sudo usermod -aG adm <пользователь>, и помните, что это доступ ко всем журналам сервера;
  • в логи попадает больше, чем кажется: sudo записывает выполненные команды вместе с аргументами (так работает классический sudo из 24.04), а в access.log веб-сервера — весь адрес запроса, включая параметры. Пароль или токен в аргументе команды или в ?token=… окажется в журнале, поэтому секреты так не передают;
  • не включайте LogLevel DEBUG для sshd надолго: документация предупреждает, что это нарушает приватность пользователей;
  • перед отправкой журнала коллегам или в поддержку просмотрите его и удалите адреса, имена и секреты;
  • тот, кто получил root, может изменить локальный журнал. Копия на другом сервере сохранит запись о случившемся.

Пересылка логов на другой сервер

В Windows для этого есть Windows Event Forwarding: события выбранных компьютеров попадают на сервер сбора. В Linux то же делает rsyslog. Ниже обзор на безопасном примере: пересылаем одну учебную facility local5 (её сообщения мы создадим в практике), а не всё подряд. Пересылка всего журнала открытым текстом, включая auth с командами sudo, для боевой схемы не годится.

На отправителе (lnx1) создайте /etc/rsyslog.d/90-forward.conf:

local5.* action(type="omfwd" Target="192.168.10.21" Port="514" Protocol="tcp")

На сервере журналов (lnx2) создайте /etc/rsyslog.d/10-listen.conf с приёмом по TCP (в пакетном /etc/rsyslog.conf такие строки закомментированы, но править файл пакета не нужно). Если ufw на lnx2 включён (см. врезку «Состояние стенда» в статье про Ansible), разрешите порт только отправителю:

module(load="imtcp")
input(type="imtcp" port="514")
sudo ufw allow from 192.168.10.20 to any port 514 proto tcp

На обоих серверах проверьте sudo rsyslogd -N1 и перезапустите службу (sudo systemctl restart rsyslog). Тест: на lnx1 выполните logger -p local5.notice -t myapp "forward test", на lnx2 запись появится в /var/log/syslog. Откат:

# на lnx1
sudo rm /etc/rsyslog.d/90-forward.conf
sudo systemctl restart rsyslog
# на lnx2
sudo rm /etc/rsyslog.d/10-listen.conf
sudo systemctl restart rsyslog
sudo ufw delete allow from 192.168.10.20 to any port 514 proto tcp

Что нужно знать об этом:

  • UDP теряет сообщения, обычный TCP — реже, но тоже может при обрыве соединения. rsyslog умеет буферизовать сообщения в очереди, пока сервер журналов недоступен; настройка очередей описана в документации rsyslog;
  • без шифрования сообщения идут открытым текстом и могут быть подделаны или повторены. Шифрование (TLS) мы не настраиваем: изучите его по документации rsyslog, прежде чем пересылать что-то секретное;
  • принимающий сервер можно завалить сообщениями, пока на диске не кончится место, поэтому порт открывают только известным отправителям и никогда в интернет, а журналы кладут на отдельную файловую систему.

Практика: сбой службы, свой лог и размер журнала

Выполняйте на тестовой машине.

Шаг 1. Находим причину сбоя. Создадим службу, которая падает из-за отсутствия файла настроек. Скрипт /usr/local/bin/logdemo.sh (создайте через sudo nano):

#!/bin/bash
echo "logdemo: starting"
if [[ ! -r /etc/logdemo.conf ]]; then
  echo "<3>logdemo: cannot read /etc/logdemo.conf"
  exit 1
fi
echo "logdemo: config loaded, working"
sleep 3600

Юнит /etc/systemd/system/logdemo.service:

[Unit]
Description=Log demo service

[Service]
Type=exec
DynamicUser=yes
SyslogIdentifier=logdemo
ExecStart=/usr/local/bin/logdemo.sh

DynamicUser=yes создаёт временного пользователя на время работы, отдельная учётная запись не нужна. Запустим и посмотрим:

sudo chmod 755 /usr/local/bin/logdemo.sh
sudo systemctl daemon-reload
sudo systemctl start logdemo
systemctl status logdemo --no-pager
sudo journalctl -u logdemo --no-pager
sudo journalctl -u logdemo -p err --no-pager

В status будет failed и код выхода 1. Пример записей журнала:

Nov 04 14:02:11 lnx1 logdemo[2301]: logdemo: starting
Nov 04 14:02:11 lnx1 logdemo[2301]: logdemo: cannot read /etc/logdemo.conf
Nov 04 14:02:11 lnx1 systemd[1]: logdemo.service: Main process exited, ...
Nov 04 14:02:11 lnx1 systemd[1]: logdemo.service: Failed with result ...

Причина указана в записи cannot read /etc/logdemo.conf. Вывод с -p err короче: в нём нет строки starting, потому что у неё нет префикса уровня. Исправим причину и проверим результат:

sudo touch /etc/logdemo.conf
sudo systemctl restart logdemo
systemctl status logdemo --no-pager

Шаг 2. Свой лог и его ротация. Правило rsyslog, которое пишет сообщения facility local5 в отдельный файл. Файл /etc/rsyslog.d/30-myapp.conf:

local5.*    /var/log/myapp.log
sudo rsyslogd -N1
sudo systemctl restart rsyslog
logger -p local5.notice -t myapp "test message"
sudo ls -l /var/log/myapp.log
sudo cat /var/log/myapp.log

Файл должен принадлежать syslog:adm с правами -rw-r----- (так настроен rsyslog), а строка начинается с метки времени. Теперь правило ротации, файл /etc/logrotate.d/myapp. Директиву su root adm мы повторяем из общего файла, чтобы правило работало и при отдельном запуске:

/var/log/myapp.log {
    su root adm
    weekly
    rotate 4
    compress
    delaycompress
    missingok
    notifempty
    create 0640 syslog adm
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}
sudo logrotate -d -f /etc/logrotate.d/myapp
sudo logrotate -f /etc/logrotate.d/myapp
sudo ls -l /var/log/myapp.log*

Первая команда только показывает, что произошло бы. Вторая действительно ротирует. После неё рядом с новым пустым myapp.log появится myapp.log.1 без сжатия (из-за delaycompress). Чтобы увидеть сжатие, запишите в лог ещё строку (logger -p local5.notice -t myapp "second") и повторите sudo logrotate -f /etc/logrotate.d/myapp: myapp.log.1 станет myapp.log.2.gz. Без новой строки notifempty пропустит пустой файл даже при -f. Резервные копии правил (например myapp.bak) в /etc/logrotate.d/ не оставляйте: logrotate читает все файлы каталога, кроме имён с «запрещёнными» расширениями (~, .dpkg-old и подобных), а .bak в их список не входит, и копия будет прочитана как ещё одно правило.

Шаг 3. Ограничиваем журнал. Посмотрим размер и зададим лимиты:

journalctl --disk-usage
sudo mkdir -p /etc/systemd/journald.conf.d
sudo nano /etc/systemd/journald.conf.d/50-size.conf
[Journal]
SystemMaxUse=200M
MaxRetentionSec=1month
sudo systemctl restart systemd-journald
systemd-analyze cat-config systemd/journald.conf
journalctl --disk-usage

Перезапускать systemd-journald безопасно (останавливать его не рекомендуется). Лимит применяется к архивным файлам, поэтому размер может уменьшиться не сразу.

Уборка.

sudo systemctl stop logdemo
sudo systemctl reset-failed logdemo
sudo rm /etc/systemd/system/logdemo.service /usr/local/bin/logdemo.sh
sudo rm /etc/logdemo.conf
sudo systemctl daemon-reload
sudo rm /etc/rsyslog.d/30-myapp.conf /etc/logrotate.d/myapp
sudo systemctl restart rsyslog
sudo rm /var/log/myapp.log*
sudo rm /etc/systemd/journald.conf.d/50-size.conf
sudo systemctl restart systemd-journald

Если пробовали пересылку, сделайте откат из её раздела.

Типичные ошибки и недоразумения

  • Удалили огромный лог, а df показывает прежнее. Файл удалён, но служба держит его открытым, и место освободится только после перезапуска службы. Живой файл безопаснее обнулить: sudo truncate -s 0 <файл>. Найти виновников поможет sudo du -xh --max-depth=1 /var/log и journalctl --disk-usage.
  • -p err ничего не нашёл, а ошибка есть. Строки из стандартного вывода служб имеют обычный уровень, пока программа не поставит префикс <3>. Попробуйте поиск по тексту -g.
  • Журнал за прошлую загрузку пуст. Скорее всего, журнал хранится только в памяти (подробнее в статье про службы).
  • logrotate -f ничего не ротирует. Файл пуст, а в правиле стоит notifempty: он отменяет даже принудительную ротацию.
  • Правило logrotate «не работает». Запуск идёт раз в сутки: проверьте logrotate -d и /var/lib/logrotate/status. Забытый postrotate оставляет службу пишущей в переименованный файл.
  • *В /etc/logrotate.d лежит `.bak.** Имя без «запрещённого» расширения читается как правило, и появляются дубли. Храните копии в/root`.
  • rsyslog не пишет в нестандартный каталог. Это AppArmor, а не права файловой системы: см. раздел про rsyslog.
  • Время в журнале «не то». journalctl показывает ваш часовой пояс; для сравнения с другим сервером добавьте --utc и проверьте синхронизацию времени (статья 02).

Проверьте себя

  1. Чем journald отличается от rsyslog и почему одно событие видно и в journalctl, и в /var/log/syslog? journald хранит структурированный двоичный журнал с метаданными, rsyslog раскладывает сообщения по текстовым файлам по правилам facility и priority. В Ubuntu journald пересылает копию сообщений rsyslog (ForwardToSyslog=yes в файле пакета), поэтому события дублируются.
  2. Как показать ошибки службы nginx за предыдущую загрузку? sudo journalctl -u nginx -b -1 -p err; для этого журнал должен храниться на диске.
  3. Что делают logrotate -d и logrotate -f? -d — режим отладки: ничего не меняет и не обновляет файл состояния, только печатает, что было бы сделано; -f принуждает к ротации, даже если срок не подошёл (пустой файл при notifempty она всё равно пропустит).
  4. Зачем в правиле logrotate для файлов rsyslog нужен postrotate? Демон держит файл открытым и после переименования продолжает писать в старую копию. Скрипт посылает rsyslog сигнал HUP, и он открывает файл заново.
  5. Кто может читать /var/log/auth.log и чем опасно давать доступ к логам? root и члены группы adm; журналы содержат имена пользователей, адреса, команды sudo и случайно попавшие секреты. Члена adm стоит добавлять только администраторам, а секреты нельзя передавать в командной строке и в адресах.

Что дальше

Источники

Ещё по теме «Linux»