journalctl: как выжимать максимум из системных логов в продакшене
Системные логи — это не просто набор строк, которые кто-то когда-то решил сохранить. Это источник данных, который может рассказать о проблеме задолго до того, как она проявится в метриках или алертах. В Linux журнал системных событий (journald) и его основной клиент journalctl становятся критически важными инструментами, когда система выходит из-под контроля, а стандартные лог-файлы в /var/log/ перестают давать полную картину.
Проблема в том, что многие администраторы и разработчики используют journalctl как "последнюю инстанцию" — когда уже всё рушится. На самом деле, это инструмент для проактивного мониторинга, быстрой диагностики и оптимизации производительности. Но чтобы им пользоваться эффективно, нужно знать не только базовые команды, но и как настраивать journald, как фильтровать данные и как избежать типичных ошибок.
Когда journalctl становится незаменим
Представьте сценарий:
- Сервис падает в продакшене, но в
/var/log/syslogнет нужной информации. - Новый микросервис не запускается, а в консоли — только "command not found".
- Система загружена до 90% CPU, но
topиhtopне показывают явных виновников. - Нужно проанализировать поведение системы за последние 30 дней, но ротация логов стирает данные.
В таких случаях journalctl становится ключевым источником истины. Он собирает:
- Логи от системных сервисов (systemd, kernel, пользовательские сервисы).
- Метрики производительности (CPU, memory, disk I/O).
- Сообщения об ошибках и предупреждения.
- Журналы ядра (если настроен правильно).
Но чтобы получить из этого что-то полезное, нужно знать, как искать, как фильтровать и как настраивать.
Практика: как не тонуть в потоке логов
1. Базовые команды, которые спасают время
Не все знают, что journalctl — это не просто cat /var/log/messages. Вот что действительно работает:
# Посмотреть последние 10 строк логов (по умолчанию — все)
journalctl -n 10
# Отфильтровать по сервису (например, nginx)
journalctl -u nginx --no-pager
# Показать только ошибки (priority 3 и выше)
journalctl -p err
# Логи за последние 5 минут
journalctl --since "5 minutes ago"
# Логи за конкретный период (например, вчера)
journalctl --since "2024-05-20 00:00:00" --until "2024-05-20 23:59:59"
# Логи от конкретного процесса (по PID)
journalctl _PID=1234
# Логи с определенным ключевым словом (например, "failed")
journalctl -g "failed"
# Показать только текущий бут (последний запуск системы)
journalctl -b
# Логи за предыдущий бут (если был)
journalctl -b -1
Лайфхак: Добавьте --no-pager к любой команде, если хотите сразу получить результат в терминале без пагинации.
2. Как настроить journald для своих нужд
По умолчанию journald хранит логи в бинарном формате и ротирует их. Но можно изменить поведение под свои задачи.
Пример конфигурации /etc/systemd/journald.conf:
[Journal]
# Увеличиваем максимальный размер логов до 500Мб
Storage=persistent
MaxFileSize=50M
MaxFiles=10
# Включаем сохранение логов в /var/log/journal/ (для долгого хранения)
SystemMaxUse=500M
# Сохраняем логи ядра (если нужно)
ForwardToSyslog=yes
Важно:
- После изменения конфига обязательно перезапустите journald:
sudo systemctl restart systemd-journald - Если используете
systemdна файловой системе без поддержкиxattr(например,tmpfs), логи не сохранятся при перезагрузке. В этом случае используйтеStorage=persistentи убедитесь, что/var/log/journal/существует и имеет правильные права.
3. Как вытаскивать данные для анализа
Иногда нужно не просто посмотреть логи, а экспортировать их для дальнейшего анализа. Вот как это сделать:
Экспорт в JSON для парсинга:
journalctl -u nginx --no-pager -o json > nginx_logs.json
Экспорт в CSV для анализа в Excel:
journalctl -u nginx --no-pager -o short -a | awk '{print $1, $2, $3, $4}' > nginx_logs.csv
Поиск по регулярным выражениям (например, найти все ошибки подключения к базе):
journalctl -u app-service --no-pager | grep -E "connection.*failed|timeout|error"
Пример реального кейса: В одном проекте сервис падало раз в неделю без явной причины. После анализа логов с помощью:
journalctl -u app-service --since "1 week ago" | grep -i "error\|fail\|crash"
Оказалось, что проблема была в недостаточном пуле соединений к базе данных. Логи показывали таймауты, но они "прятались" в общем шуме.
Типичные ошибки и как их избежать
Игнорирование ротации логов
- Проблема: Если не настроена ротация,
/var/log/journal/может разрастись до гигабайт и заполнить диск. - Решение: Установите
MaxFileSizeиSystemMaxUseв конфигеjournald.confи следите за использованием диска.
- Проблема: Если не настроена ротация,
Поиск по неточным ключевым словам
- Проблема: Команда
journalctl -g "error"может вернуть сотни строк, среди которых нужная информация "затеряется". - Решение: Уточняйте поиск:
journalctl -u nginx -g "50[0-9]*" # Искать ошибки 500-599
- Проблема: Команда
Забывание о фильтрации по времени
- Проблема:
journalctlпо умолчанию показывает все логи, что может занять минуты и забить терминал. - Решение: Всегда ограничивайте временной диапазон:
journalctl --since "1 hour ago" -u critical-service
- Проблема:
Неправильная настройка хранения логов
- Проблема: Если
Storage=volatile, все логи сбрасываются при перезагрузке. - Решение: Для долгого хранения используйте
Storage=persistentи убедитесь, что/var/log/journal/существует.
- Проблема: Если
Отсутствие мониторинга заполнения логов
- Проблема: Если логи не ротируются, система может разогнаться до OOM-киллера.
- Решение: Добавьте в
cronпроверку:#!/bin/bash LOG_DIR="/var/log/journal/" if [ $(du -sh $LOG_DIR | cut -f1) -gt "200M" ]; then journalctl --vacuum-size=150M fi
Когда journalctl не поможет (и что делать дальше)
Есть случаи, когда journalctl не даст нужной информации:
- Логи не записываются: Проверьте права доступа и конфиг
journald.conf. - Сервис не использует systemd: В этом случае логи могут лежать в
/var/log/<service>.logили/dev/null. - Проблема в аппаратном обеспечении: Если виноват диск или RAM, то и
journalctlне спасет — нужныdmesg,smartctlи физическая диагностика.
В таких случаях комбинируйте journalctl с другими инструментами:
# Логи ядра (если проблема на уровне hardware/driver)
dmesg | tail -n 50
# Мониторинг дисков
iostat -x 1
# Проверка памяти
free -h
vmstat 1
Практический вывод: как интегрировать journalctl в рабочий процесс
Настройте journald под свои задачи
- Определите, какие сервисы критически важны, и настройте для них отдельные правила хранения.
- Пример: Для базы данных (
postgresql) можно увеличитьMaxFileSize, а для временных сервисов — уменьшить.
Автоматизируйте экспорт логов
- Настройте
cron-задачу для экспорта важных логов в JSON/CSV раз в сутки:0 3 * * * journalctl -u critical-service --since "1 day ago" -o json > /backups/journal_logs_$(date +\%Y\%m\%d).json
- Настройте
Используйте journalctl для проактивного мониторинга
- Пишите скрипты, которые парсят логи и отправляют алерты при определенных событиях:
# Пример: алерт, если в логах nginx появляется слово "502" journalctl -u nginx --no-pager | grep "502" && curl -X POST -d "alert" http://monitoring-service/alert
- Пишите скрипты, которые парсят логи и отправляют алерты при определенных событиях:
Обучайте команду
- Многие инциденты происходят из-за того, что разработчики не знают, как искать логи. Добавьте в онбординг инструкцию по
journalctlс 3-5 ключевыми командами.
- Многие инциденты происходят из-за того, что разработчики не знают, как искать логи. Добавьте в онбординг инструкцию по
Комбинируйте с другими инструментами
journalctl— это не панацея. Умело сочетайте его с:strace(для отладки процессов).tcpdump(для сетевых проблем).perf(для анализа производительности).
Заключение: journalctl — это не просто утилита, а часть инфраструктуры
Если вы работаете с Linux-системами, journalctl должен быть в вашем арсенале не как инструмент для экстренных случаев, а как часть ежедневного мониторинга. Он помогает:
- Быстрее находить корень проблем.
- Автоматизировать сбор метрик.
- Сохранять историю событий для постмортема.
Главный совет: Начните с базовых команд, затем настройте journald под свои нужды, и наконец — автоматизируйте работу с логами. Это сэкономит часы в будущем, когда система начнет "вести себя странно", а вам нужно будет найти источник проблемы за 5 минут, а не за 5 часов.
А теперь — практика. Попробуйте сами:
- Запустите
journalctl -u <ваш_сервис>и посмотрите, какие логи приходят. - Настройте ротацию для одного из сервисов.
- Напишите скрипт, который раз в день архивирует логи для критически важных сервисов.
Если вы сделаете это, то уже через неделю заметите, как сильно упростится жизнь в поддержке.