Перейти к содержимому

journalctl: фильтрация и форматирование логов systemd

Логи пропали. Сервер перезагрузили — и привычный less /var/log/syslog молчит. В современных дистрибутивах с systemd логи собирает journald, а читает их journalctl. Если не знать его фильтры, работа с системой превращается в гадание.

Почему логи исчезают после перезагрузки

По умолчанию journal хранит данные в /run/log/journal/ — это tmpfs, сбрасывается при ребуте. Чтобы логи переживали перезагрузку, создайте директорию:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal

После этого перезапустите systemd-journald:

sudo systemctl restart systemd-journald

Проверить текущее расположение и объём:

journalctl --disk-usage
Примечание

На свежих CentOS/RHEL 8+ и Fedora директория /var/log/journal создаётся автоматически. На Debian/Ubuntu — обычно нет.

Фильтрация по юниту и диапазону времени

Самый частый кейс — логи конкретного сервиса:

journalctl -u nginx.service
journalctl -u postgresql@main.service

Комбинируйте несколько юнитов через повтор флага:

journalctl -u nginx.service -u php-fpm.service

Временные фильтры — для отладки инцидентов:

# Последний час
journalctl --since "1 hour ago"

# Конкретный день
journalctl --since "2025-01-15" --until "2025-01-15 23:59:59"

# За последние сутки
journalctl --since "yesterday"

# С 08:00 до 09:00
journalctl --since "today 08:00" --until "today 09:00"

Столкнулись с падением ночью — смотрите логи за тот период, а не весь буфер.

Предупреждение

Если временной фильтр возвращает пустой вывод — проверьте часовой пояс. journalctl хранит метки в UTC, а --since интерпретирует локальное время.

Фильтрация по приоритету

Уровни логов соответствуют syslog:

УровеньЧислоОписание
emerg0Система неработоспособна
alert1Требуется немедленное действие
crit2Критическая ошибка
err3Ошибка
warning4Предупреждение
notice5Заметное событие
info6Информационное
debug7Отладочное
# Только ошибки и критические
journalctl -p err -l

# Ошибки и предупреждения
journalctl -p warning..err

# Все уровни от notice и выше
journalctl -p notice

Флаг -l показывает полные hostname вместо сокращённых.

Просмотр логов ядра и загрузки

Ядро шлёт свои сообщения отдельно. Флаг -k заменяет dmesg:

# Ядро за текущую загрузку
journalctl -k

# Ядро за предыдущую загрузку
journalctl -k -b -1

Список всех загрузок:

journalctl --list-boots

Вывод:

-2 5d3c1a9... Mon 2025-01-13 08:00:00 — Mon 2025-01-13 18:00:00
-1 a7b2d8f... Mon 2025-01-13 18:05:00 — Tue 2025-01-14 08:00:00
 0 c9e1f3a... Tue 2025-01-14 08:05:00 — currently running

Выбрать конкретную загрузку:

journalctl -b 5d3c1a9...

Для анализа загрузки используйте systemd-analyze:

systemd-analyze blame | head -20
systemd-analyze critical-chain nginx.service

Поиск по регулярному выражению

Грепать вывод journalctl бессмысленно — теряете метаданные. Вместо этого -g (–grep):

# Искать ошибки подключения к БД
journalctl -g "connection.*failed" -u myapp.service

# Ошибки аутентификации
journalctl -g "auth.*fail" -p err

-g поддерживает базовые регулярки. Для сложных условий комбинируйте с --since:

journalctl -u nginx.service --since "1 hour ago" | grep -E "(timeout|502|503)"

Так вы держите выборку по юниту и времени, а затем фильтруете по паттерну.

Follow-режим (-f)

Аналог tail -f для journald. В отличие от слежения за файлом, follow работает с любым фильтром:

journalctl -u nginx.service -f
journalctl -f -p err
journalctl -u nginx.service -p err -f

В терминале Ctrl+C останавливает follow. Из скрипта — через timeout или сигнал.

Подсказка

Запускайте -f в отдельном окне tmux/screen. Если окно закроется, логи продолжат писаться в journald — данные не потеряются.

Флаги комбинируются через AND: -u nginx -p err покажет ошибки только из nginx. Для OR по юнитам используйте поля journald:

journalctl --no-pager _SYSTEMD_UNIT=nginx.service OR _SYSTEMD_UNIT=php-fpm.service -p err

Другие полезные поля:

# По UID
journalctl --no-pager _UID=1000

# По executable
journalctl --no-pager _EXE=/usr/sbin/nginx

# Список значений поля
journalctl --no-pager -F _SYSTEMD_UNIT

Форматы вывода

По умолчанию journalctl pager’ит вывод. Для скриптов и передачи в jq нужна машиночитаемая форма:

# JSON Lines (jq-friendly)
journalctl -u nginx -n 50 -o json

# JSON со структурой
journalctl -u nginx -n 50 -o json-pretty
ФлагОписаниеПрименение
-o shortКлассический syslogПо умолчанию
-o short-isoВремя в ISO 8601Логирование в SIEM
-o short-preciseМиллисекундыТочный тайминг
-o verboseВсе поляМаксимум деталей
-o jsonJSON Linesjq, Splunk, ELK
-o catТолько MESSAGEМинимализм
# Только сообщения, без метаданных — аналог tail -f /var/log/app.log
journalctl -u myapp -f -o cat
Подсказка

-n 100 ограничивает вывод последними 100 строками. --no-pager отключает pager для скриптов.

Очистка и управление размером журнала

journald ротирует логи по размеру и времени. Настраивается в /etc/systemd/journald.conf:

[Journal]
SystemMaxUse=500M
SystemMaxFileSize=50M
MaxRetentionSec=30day

Применить без рестарта:

sudo systemd-tmpfiles --create /etc/tmpfiles.d/journald.conf
sudo killall -USR1 systemd-journald

Очистить место вручную:

# Показать занимаемое место
journalctl --disk-usage

# Удалить логи старше N дней
sudo journalctl --vacuum-time=7days

# Удалить логи, оставив последние N мегабайт
sudo journalctl --vacuum-size=200M

# Удалить старые файлы журнала (не текущий)
sudo journalctl --vacuum-files=5
Предупреждение

--vacuum-* удаляет только файлы, превышающие лимит. Чтобы освободить место наверняка, увеличьте SystemMaxUse и перезапустите journald.

Типичные ошибки

journalctl: cannot open files — нет прав. Добавьте себя в группу systemd-journal:

sudo usermod -aG systemd-journal $USER
# перелогиниться

Логи пустые после перезагрузки — не настроено персистентное хранилище (первая секция).

journalctl зависает — огромный буфер. Начните с -b или ограничьте время --since.

Нет логов юнита — проверьте, что юнит вообще запускался:

systemctl status nginx
journalctl -u nginx --no-pager -n 20

journalctl заточен под быстрый поиск. Не читайте логи глазами — фильтруйте сразу.