Инструкция

Логи в Linux: journalctl, /var/log, rsyslog и logrotate

Обновлено: · Skillaria.Top

В современных дистрибутивах Linux логи собирает journald, а читают их командой journalctl: journalctl -u nginx покажет записи одного сервиса, -f — поток в реальном времени, --since и -p фильтруют по времени и важности. Текстовые логи лежат в /var/log, их пишет rsyslog или само приложение, а logrotate регулярно сжимает и удаляет старые файлы, чтобы диск не переполнился.

Когда сервис упал ночью, ответ почти всегда есть в логах — вопрос только в том, где их искать. В современных дистрибутивах (Ubuntu, Debian, RHEL, Fedora, Arch) события собирает служба journald, а читаются они командой journalctl. Параллельно многие программы пишут обычные текстовые файлы в /var/log, и за их размером следит logrotate. Ниже — как работать с journalctl логами Linux на практике, где лежат остальные журналы и как не потерять важное при ротации.

Где хранятся логи в Linux

Источников три, и полезно держать их в голове как карту:

  • journald — бинарный журнал systemd. Принимает stdout и stderr всех сервисов, сообщения ядра и syslog. Хранится в /var/log/journal/ (постоянно) или /run/log/journal/ (до перезагрузки).
  • /var/log — текстовые файлы. Их пишет rsyslog (например, /var/log/syslog, /var/log/auth.log) или сами приложения: nginx, PostgreSQL, MySQL.
  • Кольцевой буфер ядра — сообщения драйверов и оборудования, их показывает dmesg или journalctl -k.
ФайлЧто внутри
/var/log/syslog (Debian/Ubuntu)общий системный журнал
/var/log/messages (RHEL/Fedora)то же самое в семействе Red Hat
/var/log/auth.log или /var/log/secureвходы, sudo, SSH
/var/log/kern.logсообщения ядра
/var/log/dpkg.log, /var/log/apt/установка пакетов
/var/log/nginx/access.log и error.log веб-сервера
/var/log/wtmp, /var/log/btmpбинарные журналы входов, читаются через last и lastb

Большинство файлов в /var/log доступны только root или группе adm, поэтому команды чтения часто нужно запускать через sudo.

journalctl: базовые команды

Без аргументов journalctl выводит весь журнал от самых старых записей через пейджер less. Это редко нужно — обычно сразу сужают выборку.

journalctl              # весь журнал, от старых к новым
journalctl -e           # открыть сразу в конце
journalctl -n 50        # последние 50 строк
journalctl -r           # в обратном порядке, новые сверху
journalctl --no-pager   # без less, удобно для скриптов и grep

Внутри пейджера работают привычные клавиши less: / — поиск, G — в конец, q — выход. Длинные строки обрезаются по ширине экрана; стрелки влево и вправо прокручивают их.

Логи конкретного сервиса: journalctl -u

Самый частый сценарий — посмотреть, что писал один юнит systemd. Искать файл и грепать его не нужно:

$ sudo journalctl -u nginx -n 20
Oct 14 03:12:41 web1 systemd[1]: Starting nginx.service - A high performance web server...
Oct 14 03:12:41 web1 nginx[1834]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Failed with result 'exit-code'.

Флаг -u можно повторять: journalctl -u nginx -u php8.2-fpm покажет оба сервиса вперемешку по времени, что удобно, когда ошибка возникает на стыке. Для пользовательских юнитов (systemctl --user) используйте journalctl --user -u имя.

Логи в реальном времени: journalctl -f

sudo journalctl -u nginx -f

Это аналог tail -f: команда выводит последние 10 записей и ждёт новых. Удобно держать её в отдельном терминале, пока вы перезапускаете сервис или воспроизводите ошибку. Выход — Ctrl+C.

Фильтры по времени и загрузке

Если вы знаете, когда случилась авария, выборку по времени задают флагами --since и --until. Они понимают и точные даты, и относительные значения:

journalctl --since "2026-10-14 02:50" --until "2026-10-14 03:30"
journalctl --since "1 hour ago"
journalctl --since yesterday --until today
journalctl -u nginx --since "10 min ago"

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

$ journalctl --list-boots
 -2 8f1c...  Sat 2026-10-12 09:01:12 UTC  Sun 2026-10-13 22:47:03 UTC
 -1 a7d2...  Sun 2026-10-13 22:48:30 UTC  Tue 2026-10-14 03:05:51 UTC
  0 c3e9...  Tue 2026-10-14 03:07:02 UTC  Tue 2026-10-14 09:15:40 UTC

$ journalctl -b -1 -e      # конец предыдущей загрузки
$ journalctl -b            # только текущая загрузка

Список загрузок доступен, только если журнал хранится на диске. Как это включить — ниже, в разделе про настройку journald.

Фильтр по важности: journalctl -p

Каждая запись имеет приоритет syslog от 0 до 7. Флаг -p показывает указанный уровень и всё, что важнее:

КодИмяКогда используется
0emergсистема неработоспособна
1alertнужно немедленное вмешательство
2critкритическая ошибка
3errошибка
4warningпредупреждение
5noticeзначимое, но нормальное событие
6infoинформационное сообщение
7debugотладка
journalctl -p err -b              # все ошибки с начала загрузки
journalctl -p warning..err -u ssh # диапазон уровней для одного сервиса

Команда journalctl -p err -b — хорошая первая проверка после перезагрузки или обновления: она за секунды показывает, что пошло не так.

Поиск и другие фильтры

journald хранит у каждой записи структурированные поля, и по ним можно фильтровать без grep:

journalctl _PID=1834                 # по номеру процесса
journalctl _COMM=sshd                # по имени программы
journalctl _UID=1000                 # по пользователю
journalctl /usr/sbin/sshd            # по пути к исполняемому файлу
journalctl -k                        # только сообщения ядра (как dmesg)
journalctl -t CRON                   # по идентификатору syslog
journalctl -g "Out of memory"        # поиск по тексту, регулярное выражение

Флаг -g (--grep) появился в systemd 237; на старых системах используйте обычный конвейер journalctl --no-pager | grep .... Фильтры по разным полям объединяются через «И», так что journalctl -u nginx -p err --since today вернёт только сегодняшние ошибки nginx.

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

Флаг -o меняет формат. Самые полезные варианты:

  • -o short-iso — время в ISO 8601, удобно сравнивать с логами приложения.
  • -o verbose — все поля записи, включая _SYSTEMD_UNIT, _PID, _BOOT_ID.
  • -o json или json-pretty — для обработки скриптом или jq.
  • -o cat — только текст сообщения, без даты и хоста.
journalctl -u myapp -o json --since today | jq -r '.MESSAGE'

Настройка journald: хранение и размер

Настройки лежат в /etc/systemd/journald.conf (переопределения удобнее класть в /etc/systemd/journald.conf.d/*.conf). Главный параметр — Storage:

  • persistent — журнал пишется на диск в /var/log/journal и переживает перезагрузку.
  • volatile — только в памяти, в /run/log/journal.
  • auto (по умолчанию) — на диск, если каталог /var/log/journal существует.

На некоторых минимальных образах каталога нет, и после перезагрузки история пропадает. Включить постоянное хранение:

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

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

# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=1month

По умолчанию SystemMaxUse — 10% от размера файловой системы, но не больше 4 ГБ.

Как очистить журнал journalctl

$ journalctl --disk-usage
Archived and active journals take up 1.8G in the file system.

sudo journalctl --vacuum-size=300M   # оставить не больше 300 МБ
sudo journalctl --vacuum-time=2weeks # удалить записи старше двух недель
sudo journalctl --rotate             # закрыть активные файлы, чтобы их тоже можно было удалить

Удалять файлы из /var/log/journal через rm не стоит: vacuum делает то же аккуратно и не трогает активный файл.

rsyslog: классические текстовые логи

rsyslog — демон, который принимает сообщения syslog (в том числе пересланные из journald) и раскладывает их по файлам по правилам. Конфигурация — /etc/rsyslog.conf и /etc/rsyslog.d/*.conf. Правило состоит из селектора источник.уровень и действия:

# /etc/rsyslog.d/50-default.conf (фрагмент)
auth,authpriv.*        /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
kern.*                 -/var/log/kern.log

Минус перед путём означает запись без синхронизации на диск после каждой строки — быстрее, но при аварии последние строки могут потеряться. После изменения конфигурации проверьте синтаксис и перезапустите службу:

sudo rsyslogd -N1
sudo systemctl restart rsyslog

Главное, ради чего rsyslog держат рядом с journald, — пересылка логов на центральный сервер. Одна строка отправит всё по TCP:

# /etc/rsyslog.d/90-remote.conf
*.* @@logs.example.com:514

Один символ @ означает UDP, два @@ — TCP. Если сервер умрёт целиком, копия логов останется на другой машине. Чтобы записать своё сообщение в системный журнал из скрипта, используйте logger:

logger -t backup -p user.err "Бэкап базы не удался"
journalctl -t backup -n 5

logrotate: ротация логов

Текстовые логи растут бесконечно, пока их кто-то не обрежет. Этим занимается logrotate: раз в сутки (через cron или таймер logrotate.timer) он переименовывает текущий файл, сжимает старые и удаляет самые давние. Общие настройки — /etc/logrotate.conf, правила для программ — /etc/logrotate.d/.

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 myapp adm
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}
ДирективаСмысл
daily / weekly / size 100Mкогда ротировать
rotate 14сколько старых файлов хранить
compress, delaycompressсжимать gzip, но самый свежий архив оставить несжатым
missingok, notifemptyне ругаться на отсутствие файла, не ротировать пустой
create 0640 user groupс какими правами создать новый файл
copytruncateскопировать и обнулить файл — для программ, которые не умеют переоткрывать лог
postrotate ... endscriptкоманда после ротации, обычно сигнал приложению переоткрыть файл

Проверить правило без изменений и принудительно запустить ротацию:

sudo logrotate -d /etc/logrotate.d/myapp   # сухой прогон с отладкой
sudo logrotate -f /etc/logrotate.d/myapp   # ротировать прямо сейчас

Типичная ошибка — забыть postrotate или copytruncate. Тогда приложение продолжает писать в переименованный app.log.1 по старому дескриптору, а новый app.log остаётся пустым.

Чтение текстовых логов

Для файлов в /var/log хватает стандартных утилит:

sudo tail -n 100 /var/log/syslog          # последние строки
sudo tail -F /var/log/nginx/error.log     # следить, переживая ротацию
sudo less +G /var/log/auth.log            # открыть в конце
sudo zgrep "Failed password" /var/log/auth.log.*.gz   # поиск в сжатых архивах
sudo grep -c " 500 " /var/log/nginx/access.log        # сколько ответов 500

Обратите внимание на tail -F с заглавной буквой: в отличие от -f, он заново открывает файл, когда logrotate его подменяет.

Пошаговый разбор аварии

Сценарий «сервис упал ночью» удобно разбирать по одному порядку:

  1. systemctl status myapp — текущее состояние и последние строки журнала.
  2. journalctl -u myapp --since "03:00" --until "03:30" — что сервис писал в момент падения.
  3. journalctl -p err -b — нет ли других ошибок в системе в то же время.
  4. journalctl -k --since "03:00" -g "Out of memory|Killed process" — не убил ли процесс OOM killer ядра.
  5. Логи самого приложения в /var/log/myapp/, включая архивы .gz.
  6. Если сервер перезагружался — journalctl -b -1 -e.

Итог

Для повседневной работы с логами в Linux достаточно нескольких команд: journalctl -u для сервиса, -f для потока, --since и -p err для сужения выборки, -b -1 для разбора перезагрузки. Текстовые журналы лежат в /var/log, rsyslog раскладывает и пересылает их, а logrotate и journalctl --vacuum-* не дают логам съесть диск. Работа с journalctl, ротацией и диагностикой нагрузки разобрана на практике в лекции курса по Linux.

Частые вопросы

Почему journalctl показывает только записи с последней загрузки?

Журнал хранится в памяти (/run/log/journal). Создайте каталог /var/log/journal или задайте Storage=persistent в journald.conf и перезапустите systemd-journald.

Как дать обычному пользователю читать системный журнал без sudo?

Добавьте его в группу systemd-journal (или adm в Debian и Ubuntu): sudo usermod -aG systemd-journal имя, затем перелогиньтесь.

Можно ли посмотреть журнал другой системы, например с подключённого диска?

Да, укажите каталог журнала флагом -D: journalctl -D /mnt/var/log/journal. Флаг --file читает отдельный файл .journal.

Нужен ли rsyslog, если есть journald?

Не обязательно. Он полезен, если нужны текстовые файлы для старых инструментов или пересылка логов на центральный сервер; на многих минимальных образах его уже не ставят.

Как экспортировать логи сервиса в файл, чтобы отправить коллеге?

Выполните journalctl -u имя --since today --no-pager > service.log — получится обычный текстовый файл.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Linux: с нуля до уверенного администрирования».

Перейти к курсу