Состояние перевода: На этой странице представлен перевод статьи systemd/Journal. Дата последней синхронизации: 10 декабря 2021. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.
systemd использует журнал (journal), собственную систему ведения логов, в связи с чем больше не требуется запускать отдельный демон логирования. Для чтения логов используйте команду journalctl(1).
В Arch Linux каталог /var/log/journal/
— это часть пакета systemd и по умолчанию (когда в конфигурационном файле /etc/systemd/journald.conf
параметру Storage=
задано значение auto
) журнал записывается именно в /var/log/journal/
. Если каталог будет удалён, systemd не пересоздаст его автоматически и вместо этого будет вести журнал в /run/systemd/journal
без сохранения между перезагрузками. Однако каталог будет пересоздан, если добавить Storage=persistent
в journald.conf
и перезапустить systemd-journald.service
(или перезагрузиться).
Сообщения в журнале классифицируются по уровню приоритета и категории (Facility). Классификация записей соответствует классическому протоколу Syslog (RFC 5424).
Уровни приоритета
Коды важности syslog (в systemd называются приоритетами) используются для пометки важности сообщений RFC 5424.
Значение | Важность | Ключевое слово | Описание | Примеры |
---|---|---|---|---|
0 | Emergency | emerg | Cистема не работоспособна | Серьёзный баг в ядре, дамп памяти systemd. Данный уровень не должен использоваться приложениями. |
1 | Alert | alert | Cистема требует немедленного вмешательства | Отказ важной подсистемы. Потеря данных. kernel: BUG: unable to handle kernel paging request at ffffc90403238ffc .
|
2 | Critical | crit | Cостояние системы критическое | Аварийные отказы, дампы памяти. Например, знакомое сообщение:systemd-coredump[25319]: Process 25310 (plugin-containe) of user 1000 dumped core Отказ основных приложений системы, например, X11. |
3 | Error | err | Cообщения об ошибках | Сообщение о некритической ошибке:kernel: usb 1-3: 3:1: cannot get freq at ep 0x84 ,systemd[1]: Failed unmounting /var. ,libvirtd[1720]: internal error: Failed to initialize a valid firewall backend
|
4 | Warning | warning | Предупреждения о возможных проблемах | В некорневой файловой системе остался всего 1 ГБ свободного места.org.freedesktop. Notifications[1860]: (process:5999): Gtk-WARNING **: Locale not supported by C library. Using the fallback 'C' locale .
|
5 | Notice | notice | Cообщения о нормальных, но важных событиях | systemd[1]: var.mount: Directory /var to mount over is not empty, mounting anyway ,gcr-prompter[4997]: Gtk: GtkDialog mapped without a transient parent. This is discouraged
|
6 | Informational | info | Информационные сообщения | lvm[585]: 7 logical volume(s) in volume group "archvg" now active
|
7 | Debug | debug | Отладочные сообщения | kdeinit5[1900]: powerdevil: Scheduling inhibition from ":1.14" "firefox" with cookie 13 and reason "screen"
|
Вышеуказанные правила являются рекомендацией и окончательное решение остаётся за разработчиком приложения. Всегда возможно, что сообщение будет выше или ниже ожидаемого уровня.
Категории
Коды категорий (facility) syslog используются для указания типа программы, добавляющего сообщение в лог RFC 5424.
Код категории | Ключевое слово | Описание | Информация |
---|---|---|---|
0 | kern | Сообщения ядра | |
1 | user | Сообщения программного обеспечения пользователя | |
2 | Почтовая система | Архаический POSIX всё ещё поддерживается и иногда используется (см. mail(1) для получения более подробной информации) | |
3 | daemon | Системные службы | Все демоны, включая systemd и его подсистемы |
4 | auth | Сообщения безопасности (авторизации) | См. также код 10 |
5 | syslog | Собственные сообщения syslogd | Для реализаций syslogd (не используется в systemd, см. код 3) |
6 | lpr | Подсистема печати (архаическая подсистема) | |
7 | news | Подсистема новостных групп (архаическая подсистема) | |
8 | uucp | Подсистема UUCP (архаическая подсистема) | |
9 | clock daemon | systemd-timesyncd | |
10 | authpriv | Сообщения безопасности (авторизации) | См. также код 4 |
11 | ftp | Служба FTP | |
12 | — | Подсистема NTP | |
13 | — | Журнал аудита | |
14 | — | Аварийный журнал | |
15 | cron | Служба планирования | |
16 | local0 | Локальное использование 0 (local0) | |
17 | local1 | Локальное использование 1 (local1) | |
18 | local2 | Локальное использование 2 (local2) | |
19 | local3 | Локальное использование 3 (local3) | |
20 | local4 | Локальное использование 4 (local4) | |
21 | local5 | Локальное использование 5 (local5) | |
22 | local6 | Локальное использование 6 (local6) | |
23 | local7 | Локальное использование 7 (local7) |
Полезные категории для наблюдения: 0, 1, 3, 4, 9, 10, 15.
Фильтрация вывода
journalctl позволяет фильтровать вывод по определённым полям. Если должно быть отображено большое количество сообщений или необходима фильтрация большого промежутка времени, то вывод команды может занять значительное время.
Примеры:
- Показать сообщения с момента текущей загрузки системы:
# journalctl -b
Также пользователи часто интересуются сообщениями предыдущей загрузки (например, если произошёл невосстановимый сбой системы). Это возможно, если задать параметр флагу
-b
:journalctl -b -0
покажет сообщения с момента текущей загрузки,journalctl -b -1
— предыдущей загрузки,journalctl -b -2
— следующей за предыдущей и т.д. Для просмотра полного описания смотрите страницу справочного руководства journalctl(1), поддерживается и более мощная семантика. - Добавить пояснения к сообщениям логов из каталога сообщений, где это возможно:
# journalctl -x
Обратите внимание, что эту возможность лучше не использовать, когда излишние комментарии нежелательны — например, при добавлении копии логов в сообщение о баге или письмо в поддержку. Вывести существующие пункты каталога можно командой
journalctl --list-catalog
. - Показать сообщения, начиная с определённой даты (и, опционально, времени):
# journalctl --since="2012-10-30 18:17:16"
- Показать сообщения за последние 20 минут:
# journalctl --since "20 min ago"
- Следить за появлением новых сообщений:
# journalctl -f
- Показать сообщения конкретного исполняемого файла:
# journalctl /usr/lib/systemd/systemd
- Показать сообщения конкретного процесса:
# journalctl _PID=1
- Показать сообщения конкретного юнита:
# journalctl -u man-db.service
- Показать сообщения от пользовательской службы конкретного юнита:
$ journalctl --user -u dbus
- Показать кольцевой буфер ядра:
# journalctl -k
- Показать сообщения только с приоритетами error, critical и alert:
# journalctl -p err..alert
Также можно использовать числа, например,
journalctl -p 3..1
. Если указать одно число/уровень приоритета, например,journalctl -p 3
, то также будут показаны сообщения и с более высоким приоритетом (от 0 до 3, в данном случае). - Показать эквивалент auth.log используя фильтрацию категорий syslog:
# journalctl SYSLOG_FACILITY=10
- Если в каталоге с журналами (по умолчанию
/var/log/journal
) очень много данных, то фильтрация выводаjournalctl
может занять несколько минут. Процесс можно значительно ускорить с помощью опции--file
, указавjournalctl
только самый свежий журнал:# journalctl --file /var/log/journal/*/system.journal -f
Для получения дополнительной информации смотрите страницы справочного руководства journalctl(1), systemd.journal-fields(7) или пост в блоге Леннарта Пёттеринга.
Совет: По умолчанию journalctl отсекает части строк, которые не вписываются в экран по ширине, хотя иногда перенос строк может оказаться более предпочтительным. Управление этой возможностью производится посредством переменной окружения SYSTEMD_LESS
, в которой содержатся опции, передаваемые в less (программу постраничного просмотра, используемую по умолчанию). По умолчанию переменная имеет значение FRSXMK
(для получения дополнительной информации смотрите less(1) и journalctl(1)).
Если убрать опцию S
, будет достигнут требуемый результат. Например, запустите journalctl, как показано здесь:
$ SYSTEMD_LESS=FRXMK journalctl
Для использования такого поведения по умолчанию, экспортируйте переменную из файла ~/.bashrc
или ~/.zshrc
.
Совет: Несмотря на то, что журнал хранится в двоичном формате, содержимое сообщений не изменяется. Это означает, что их можно просматривать при помощи strings, например, для восстановления системы в окружении без systemd. Пример команды:
$ strings /mnt/arch/var/log/journal/af4967d77fba44c6b093d0e9862f6ddd/system.journal | grep -i message
Ограничение размера журнала
Если журнал сохраняется при перезагрузке, его размер по умолчанию ограничен значением в 10% от объема соответствующей файловой системы (и максимально может достигать 4 ГиБ). Например, для каталога /var/log/journal
, расположенном на корневом разделе в 20 ГиБ, максимальный размер журналируемых данных составит 2 ГиБ. На разделе же 50 ГиБ журнал сможет занять до 4 ГиБ. Текущие пределы для вашей системы можно узнать из логов systemd-journald
:
# journalctl -b -u systemd-journald
Максимальный объем постоянного журнала можно задать вручную, раскомментировав и отредактировав следующий параметр:
/etc/systemd/journald.conf
SystemMaxUse=50M
Также возможно использование конфигурационных сниппетов вместо редактирования глобального файла конфигурации. В таком случае поместите переопределения в разделе [Journal]
:
/etc/systemd/journald.conf.d/00-journal-size.conf
[Journal] SystemMaxUse=50M
Перезапустите systemd-journald.service
для применения изменений.
Для получения дополнительной информации обратитесь к странице справочного руководства journald.conf(5).
Ограничение размера для юнита
Отредактируйте файл юнита службы, которую вы хотите настроить (например, sshd), добавив параметр LogNamespace=ssh
в раздел [Service]
.
Затем создайте файл journald@ssh.conf
, скопировав содержимое файла /etc/systemd/journald.conf
. Отредактируйте его, задав необходимое значение SystemMaxUse
.
Перезапустите юнит, чтобы включилась новая служба журнала systemd-journald@ssh.service
. Логи службы из определённого «пространства имён» можно увидеть командой journalctl --namespace ssh
.
Подробнее о пространствах имён журнала см. systemd-journald.service(8) § JOURNAL NAMESPACES.
Очистка файлов журнала вручную
Файлы журнала можно удалить из директории /var/log/journal/
, к примеру, с помощью rm
или journalctl
для удаления части журналов по определённым критериям. Например:
- Удалять заархивированные файлы журнала, пока занимаемое ими место не составит менее 100 МиБ:
# journalctl --vacuum-size=100M
- Ограничить все файлы журнала хранением данных только за последние две недели:
# journalctl --vacuum-time=2weeks
Для получения дополнительной информации, обратитесь к journalctl(1).
Journald вместе с syslog
Совместимость с классической реализацией syslog можно обеспечить, перенаправляя все сообщения systemd через сокет /run/systemd/journal/syslog
. Для работы демона syslog с журналом, следует привязать его к данному сокету вместо /dev/log
(официальное сообщение).
Для перенаправления данных в сокет, в journald.conf
по умолчанию задан параметр ForwardToSyslog=no
, чтобы избежать перегрузки на систему, так как rsyslog или syslog-ng самостоятельно получают сообщения из журнала.
Смотрите Syslog-ng#Overview и Syslog-ng#syslog-ng and systemd journal или rsyslog для получения подробной информации о конфигурировании.
Перенаправление журнала в /dev/tty12
Создайте drop-in каталог /etc/systemd/journald.conf.d
и файл fw-tty12.conf
в нём со следующим содержимым:
/etc/systemd/journald.conf.d/fw-tty12.conf
[Journal] ForwardToConsole=yes TTYPath=/dev/tty12 MaxLevelConsole=info
Затем перезапустите службу systemd-journald
.
Выбор журнала для просмотра
Иногда необходимо проверить логи другой системы, например, загружаясь с работоспособной системы для восстановления неисправной. В таком случае примонтируйте диск, к примеру, в /mnt
и укажите путь журнала с помощью флага -D
/--directory
следующим образом:
# journalctl -D /mnt/var/log/journal -e
Доступ к журналу как пользователь
По умолчанию обычные пользователи могут читать только свой собственный пользовательский журнал. Чтобы дать доступ на чтение системного журнала обычному пользователю, добавьте его в группу systemd-journal
. Для групп adm
и wheel
также предоставляется доступ на чтение.
Подробнее смотрите journalctl(1) § DESCRIPTION и Пользователи и группы#Пользовательские группы.
Журналы — это один из самых важных источников информации при возникновении любых ошибок в операционной системе Linux. Я это уже много раз говорил ранее и вот сказал ещё раз. Раньше в Linux для сохранения журналов сервисов использовался отдельный демон под названием syslogd. Но с приходом системы инициализации systemd большинство функций касающихся управления сервисами перешли под её управление. В том числе и управление логами.
Теперь для просмотра логов определенного сервиса или загрузки системы необходимо использовать утилиту journalctl. В этой статье мы разберем примеры использования journalctl, а также основные возможности этой команды и её опции. По сравнению с обычными файлами журналов, у journalctl есть несколько преимуществ. Все логи находятся в одном месте, они индексируются и структурируются, поэтому к ним можно получить доступ в нескольких удобных форматах.
Синтаксис команды очень простой. Достаточно выполнить команду без опций или передав ей нужные опции. Если утилита не выводит ничего, выполните её от имени суперпользователя:
journalctl опции
А теперь давайте разберем основные опции journalctl:
- —full, -l — отображать все доступные поля;
- —all, -a — отображать все поля в выводе full, даже если они содержат непечатаемые символы или слишком длинные;
- —pager-end, -e — отобразить только последние сообщения из журнала;
- —lines, -n — количество строк, которые нужно отображать на одном экране, по умолчанию 10;
- —no-tail — отображать все строки доступные строки;
- —reverse, -r — отображать новые события в начале списка;
- —output, -o — настраивает формат вывода лога;
- —output-fields — поля, которые нужно выводить;
- —catalog, -x — добавить к информации об ошибках пояснения, ссылки на документацию или форумы там, где это возможно;
- —quiet, -q — не показывать все информационные сообщения;
- —merge, -m — показывать сообщения из всех доступных журналов;
- —boot, -b — показать сообщения с момента определенной загрузки системы. По умолчанию используется последняя загрузка;
- —list-boots — показать список сохраненных загрузок системы;
- —dmesg, -k — показывает сообщения только от ядра. Аналог вызова команды dmesg;
- —identifier, -t — показать сообщения с выбранным идентификатором;
- —unit, -u — показать сообщения от выбранного сервиса;
- —user-unit — фильтровать сообщения от выбранной сессии;
- —priority, -p — фильтровать сообщения по их приоритету. Есть восемь уровней приоритета, от 0 до 7;
- —grep, -g — фильтрация по тексту сообщения;
- —cursor, -c — начать просмотр сообщений с указанного места;
- —since, -S, —until, -U — фильтрация по дате и времени;
- —field, -F — вывести все данные из выбранного поля;
- —fields, -N — вывести все доступные поля;
- —system — выводить только системные сообщения;
- —user — выводить только сообщения пользователя;
- —machine, -M — выводить сообщения от определенного контейнера;
- —header — выводить заголовки полей при выводе журнала;
- —disk-usage — вывести общий размер лог файлов на диске;
- —list-catalog — вывести все доступные подсказки для ошибок;
- —sync — синхронизировать все не сохраненные журналы с файловой системой;
- —flush — перенести все данные из каталога /run/log/journal в /var/log/journal;
- —rotate — запустить ротацию логов;
- —no-pager — выводить информацию из журнала без возможности листать страницы;
- -f — выводить новые сообщения в реальном времени, как в команде tail;
- —vacuum-time — очистить логи, давностью больше указанного периода;
- —vacuum-size — очистить логи, чтобы размер хранилища соответствовал указанному.
Горячие клавиши journalctl
По умолчанию информация лога выводится в формате, в котором её можно листать. Давайте разберем горячие клавиши, которые вы можете для этого использовать:
- Стрелка вниз, Enter, e или j — переместиться вниз на одну строку;
- Стрелка вверх, y или k — переместиться на одну строку вверх;
- Пробел — переместиться на одну страницу вниз;
- b — переместиться на одну страницу вверх;
- Стрелка вправо, стрелка влево — горизонтальна прокрутка;
- g — перейти на первую строку;
- G — перейти на последнюю строку;
- p — перейти на позицию нужного процента сообщений. Например, 50p перенесет курсор на середину вывода;
- / — поиск по журналу;
- n — найти следующее вхождение;
- N — предыдущее вхождение;
- q — выйти.
Теперь вы знаете основные опции команды и клавиши, с помощью которых можно ею управлять. Дальше небольшая шпаргалка journalctl.
Шпаргалка по journalctl
Вывод journalctl представляет из себя цельный список всех сохраненных сообщений. Если вы запустите команду journalctl без параметров, то получите самые первые сообщения, которые были сохранены. В моем случае это данные за 13 января:
sudo journalctl
Чтобы найти именно то, что вам нужно, необходимо научится перемещаться по этому списку. Формат вывода лога довольно простой:
янв 13 20:55:55 sergiy-pc kernel: Linux version 4.15.0-43-generic
- янв 13 20:55:55 — дата и время события;
- sergiy-pc — хост, на котором произошло событие;
- kernel — источник события, обычно это программа или сервис. В данном случае ядро;
- Linux version 4.15.0-43-generic — само сообщение.
Давайте перейдем к примерам фильтрации и перемещения.
1. Просмотр логов сервисов
Самый частый случай использования journalctl — это когда вы пытаетесь запустить какой-либо сервис с помощью systemd, он не запускается и systemd выдает вам такое сообщение подобного содержания: Failed to start service use journalctl -xe for details. Система сама предлагает вам какую команду надо выполнить:
sudo journalctl -xe
Как вы помните из опций, эта команда отображает последние сообщения в журнале и добавляет к ним дополнительную информацию, если она есть. Учитывая, что последнее, что мы делали — был наш сервис, то здесь будут сообщения от него и вы быстро сможете понять почему он не запускается.
Чтобы отфильтровать сообщения только от определенного сервиса можно использовать опцию -u. Например:
sudo journalctl -eu apache2.service
2. Просмотр логов в режиме tail
С помощью опции -f можно указать утилите, что необходимо выводить новые сообщения в реальном времени:
sudo journalctl -f
В этом режиме less не поддерживается, поэтому для выхода нажмите сочетание клавиш Ctrl+C.
3. Просмотр логов загрузки
В логе journalctl содержатся все логи, в том числе и логи загрузки. Для того чтобы открыть лог последней загрузки используйте опцию -b:
sudo journalctl -b
Посмотреть список всех сохраненных загрузок можно командой:
sudo journalctl -list-boots
Теперь, чтобы посмотреть сообщения для нужной загрузки используйте её идентификатор:
sudo journalctl -b 37d5c906c9c6404682f029b2c34ec9dc
4. Фильтрация по дате
С помощью опции —since вы можете указать дату и время, начиная с которой нужно отображать логи:
sudo journalctl --since "2019-01-20 15:10:10"
Опция —until помогает указать по какую дату вы хотите получить информацию:
sudo journalctl -e --until "2019-01-20 15:05:50"
Или сразу скомбинируем две эти опции чтобы получить логи за нужный период:
sudo journalctl --since "2019-01-20 15:10:10" --until "2019-01-20 15:05:50"
Кроме даты в формате YYYY-MM-DD в этих опциях можно использовать такие слова, как yesterday, today, и tomorrow. Также допустимы конструкции 1 day ago (один день назад) или 3 hours ago (три часа назад). Ещё можно использовать знаки + и -. Например -1h30min будет означать полтора часа назад.
5. Журнал ядра
Если вы хотите посмотреть только сообщения ядра используйте опцию -k:
sudo journalctl -ek
6. Настройка формата вывода
По умолчанию journalctl выводит информацию с помощью утилиты less, в которой вы можете её удобно листать и просматривать. Но формат вывода можно изменить:
- short — используется по умолчанию;
- verbose — также, как и short, только выводится намного больше информации;
- json — вывод в формате json, одна строка лога в одной строке вывода;
- json-pretty — форматированный вывод json для более удобного восприятия;
- cat — отображать только сообщения, без метаданных.
Чтобы указать нужный формат используйте опцию -o. Например:
sudo journalctl -o json-pretty
Или:
sudo journalctl -eo json-pretty
7. Очистка логов
Сначала нужно посмотреть сколько ваши логи занимают на диске. Для этого используйте такую команду:
sudo journalctl --disk-usage
Чтобы уменьшить размер лога можно использовать опцию —vacuum-size. Например, если вы хотите, чтобы ваши файлы журналов занимали на диске не более 2 Гб, выполните команду:
sudo journalctl --vacuum-size=2G
Теперь старые логи будут удалены, пока общий объем хранилища не будет составлять 2 гигабайта. Также можно удалять логи по времени. Для этого используется опция —vacuum-time. Например, оставим только логи за последний год:
journalctl --vacuum-time=1years
Выводы
В этой статье мы разобрали как пользоваться journalctl в Linux. Наличие этой утилиты в системе не означает, что теперь вы не можете пользоваться обычными файлами логов. Большинство сервисов как и раньше пишут свои основные логи в файлы, а в лог journalctl пишутся сообщения при старте сервисов, а также различные системные сообщения.
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .
Демон инициализации systemd де-факто уже стал стандартом в современных Linux-системах. На него перешли многие многие популярные дистрибутивы: Debian, RHEL/CentOS, Ubuntu (начиная с версии 15.04). В systemd используется принципиально иной (по сравнению с традиционным инструментом syslog) подход к логгированию.
В его основе лежит централизация: cпециализированный компонент journal cобирает все системные сообщения (сообщения ядра, различных служб и приложений). Все логи сохраняются в бинарных файлах, что позволяет избежать сложностей с использованием парсеров для разных видов логов. При необходимости логи можно без проблем переконвертировать в другие форматы (более подробно об этом будет рассказано ниже).
Journal может работать как совместно с syslog, так и полностью заменить его.
Для просмотра логов используется утилита journalctl. Об особенностях и тонкостях работы с ней мы расскажем в этой статье.
Демон инициализации systemd де-факто уже стал стандартом в современных Linux-системах. На него перешли многие популярные дистрибутивы: Debian, RHEL/CentOS, Ubuntu (начиная с версии 15.04). В systemd используется принципиально иной (по сравнению с традиционным инструментом syslog) подход к логгированию.
В его основе лежит централизация: специализированный компонент journal cобирает все системные сообщения (сообщения ядра, различных служб и приложений). При этом специально настраивать отправку логов не нужно: приложения могут просто писать в stdout и stderr, a journal сохранит эти сообщения автоматически. Работа в таком режиме возможна и с Upstart, но он сохраняет все логи в отдельный файл, тогда как systemd сохраняет их в бинарной базе, что существенно упрощает систематизацию и поиск.
Хранение логов в бинарных файлах также позволяет избежать сложностей с использованием парсеров для разных видов логов. При необходимости логи можно без проблем переконвертировать в другие форматы (более подробно об этом будет рассказано ниже).
Journal может работать как совместно с syslog, так и полностью заменить его.
Для просмотра логов используется утилита journalctl. Об особенностях и тонкостях работы с ней мы расскажем в этой статье.
Установка времени
Одним из существенных недостатков syslog является сохранение записей без учёта часового пояса. В journal этот недостаток устранён: для логгируемых событий можно указывать как местное время, так и универсальное координированное время (UTC). Установка времени осуществляется с помощью утилиты timedatectl.
Просмотреть список часовых поясов можно при помощи команды:
$ timedatectl list-timezones
Установка нужного часового пояса осуществляется так:
$ timedatectl set-timezone <часовой пояс>
По завершении установки будет нелишним убедиться в том, что всё сделано правильно:
$ timedatectl status
Local time: Thu 2015-07-30 11:24:15 MSK
Universal time: Thu 2015-07-30 08:24:15 UTC
RTC time: Thu 2015-07-30 08:24:15
Time zone: Europe/Moscow (MSK, +0300)
NTP enabled: no
NTP synchronized: no
RTC in local TZ: no
DST active: n/a
В самой первой строке (Local time) должны быть показаны точное текущее время и дата.
Journalctl: просмотр логов
Для просмотра логов используется утилита journalctl.
Если ввести команду journalсtl без каких-либо аргументов, на консоль будет выведен огромный список:
-- Logs begin at Wed 2015-07-29 17:12:48 MSK, end at Thu 2015-07-30 11:24:15 MSK. --
Jul 29 17:12:48 host-10-13-37-10 systemd-journal[181]: Runtime journal is using 4.0M (max allowed 20.0M, trying to leave 30.0M free of 195.9M available → current limit 20.0M).
Jul 29 17:12:48 host-10-13-37-10 systemd-journal[181]: Runtime journal is using 4.0M (max allowed 20.0M, trying to leave 30.0M free of 195.9M available → current limit 20.0M).
Jul 29 17:12:48 host-10-13-37-10 kernel: Initializing cgroup subsys cpuset
Jul 29 17:12:48 host-10-13-37-10 kernel: Initializing cgroup subsys cpu
Jul 29 17:12:48 host-10-13-37-10 kernel: Initializing cgroup subsys cpuacct
Jul 29 17:12:48 host-10-13-37-10 kernel: Linux version 3.16.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 SMP Debian 3.16.7-ckt11-1+deb8u2 (2015-07-17)
Jul 29 17:12:48 host-10-13-37-10 kernel: Command line: BOOT_IMAGE=/boot/vmlinuz-3.16.0-4-amd64 root=UUID=b67ea972-1877-4c5b-a328-29fc0d6c7bc4 ro console=tty1 console=ttyS0 video=640x480 consoleblank=0 panic=15 c
Здесь мы привели лишь небольшой его фрагмент; на самом деле он включает гигантское количество записей.
Фильтрация логов
У утилиты journalctl есть опции, с помощью которых можно осуществлять фильтрацию логов и быстро извлекать из них нужную информацию.
Просмотр логов с момента текущей загрузки
С помощью опции -b можно просмотреть все логи, собранные с момента последней загрузки системы:
$ journalctl -b
Просмотр логов предыдущих сессий
С помощью journalctl можно просматривать информацию о предыдущих сессиях работы в системе — в некоторых случаях это бывает полезным.
Следует, однако, учитывать, что сохранение информации о предыдущих сессиях поддерживается по умолчанию не во всех дистрибутивах Linux. Иногда его требуется активировать
Для этого нужно открыть конфигурационный файл journald.conf, найти в нём раздел [Journal] и изменить значение параметра storage на persistent:
$ sudo nano /etc/systemd/journald.conf
...
[Journal]
Storage=persistent
Просмотреть список предыдущих загрузок можно с помощью команды:
$ journalctl --list-boots
0 9346310348bc4edea250555dc046b30c Thu 2015-07-30 12:39:49 MSK—Thu 2015-07-30 12:39:59 MSK
Её вывод состоит из четырёх колонок. В первой из них указывается порядковый номер загрузки, во второй — её ID, в третьей — дата и время. Чтобы просмотреть лог для конкретной загрузки, можно использовать идентификаторы как из первой, так и из второй колонки:
$ journalctl -b 0
или
$ journalctl -b 9346310348bc4edea250555dc046b30c
Фильтрация по дате и времени
В journalctl имеется также возможность просмотра логов за определённые периоды времени. Для этого используются опции —since и —until. Предположим, нам нужно просмотреть логи начиная с 17 часов 15 минут 20 июля 2015 года. Для этого потребуется будет выполнить команду:
$ journalctl --since "2015-07-20 17:15:00"
Если с опцией since не будет указано никакой даты, на консоль будут выведены логи начиная с текущей даты. Если дата указана, но при этом не указано время, будет применено значений времени по умолчанию — «00:00:00». Секунды также указывать не обязательно (в этом случае применяется значение по умолчанию — 00).
Можно воспользоваться и вот такими человекопонятными конструкциями:
$ journalctl ---since yesterday
$ journalctl --since 09:00 --until now
$ journalctl --since 10:00 --until "1 hour ago"
Фильтрация по приложениям и службам
Для просмотра логов конкретного приложения или службы используется опция -u, например:
$ journalctl -u nginx.service
Приведённая команда выведет на консоль логи веб-сервера nginx.
Нередко возникает необходимость просмотреть логи какой-либо службы за определённый период времени. Это можно сделать при помощи команды вида:
$ journalctl -u nginx.service --since yesterday
C опцией -u также используется фильтрация по дате и времени, например:
$ journalctl -u nginx.service -u php-fpm.service —since today
Благодаря этому можно отслеживать взаимодействие различных служб и получать информацию, которую нельзя было бы получить при отслеживании соответствующих процессов по отдельности.
Фильтрация по процессам, пользователям и группам
Просмотреть логи для какого-либо процесса можно, указав в команде journalctl его идентификационный номер (PID), например:
$ journalctl _PID=381
Для просмотра логов процессов, запущенных от имени определённого пользователя или группы, используются фильтры _UID и _GID соответственно. Предположим, у нас имеется веб-сервер, запущенный от имени пользователя www-data. Определим сначала ID этого пользователя:
$id -u www-data
33
Теперь можно просмотреть логи всех процессов, запущенных от имени этого пользователя:
$ journalctl _UID=33
Вывести на консоль список пользователей, о которых имеются записи в логах, можно так:
$ journalctl -F _UID
Для просмотра аналогичного списка пользовательских групп используется команда:
$ journalctl -F _GUID
С командной journalctl можно использовать и другие фильтры. Просмотреть список всех доступных фильтров можно, выполнив команду
$ man systemd.journal-fields
Фильтрация по пути
Просмотреть логи для какого-либо процесса также можно, указав путь к нему, например:
$ journalctl /usr/bin/docker
Иногда таким способом можно получить более подробную информацию (например, просмотреть записи для всех дочерних процессов).
Просмотр сообщений ядра
Для просмотра сообщений ядра используется опция -k или −−dmesg:
$ journalctl -k
Приведённая команда покажет все сообщения ядра для текущей загрузки. Чтобы просмотреть сообщения ядра для предыдущих сессий, нужно воспользоваться опцией -b и указать один из идентификаторов сессии (порядковый номер в списке или ID):
$ journalctl -k -b -2
Фильтрация сообщений по уровню ошибки
Во время диагностики и исправления неполадок в системе нередко требуется просмотреть логи и выяснить, есть ли в них сообщения о критических ошибках. Специально для этого в journalctl предусмотрена возможность фильтрации по уровню ошибки. Просмотреть сообщения обо всех ошибках, имевших место в системе, можно с помощью опции -p:
$ journalctl -p err -b
Приведённая команда покажет все сообщения об ошибках, имевших место в системе.
Эти сообщения можно фильтровать по уровню. В journal используется такая же классификация уровней ошибок, как и в syslog:
- 0 — EMERG (система неработоспособна);
- 1 — ALERT (требуется немедленное вмешательство);
- 2 — CRIT (критическое состояние);
- 3 — ERR (ошибка);
- 4 — WARNING (предупреждение);
- 5 — NOTICE (всё нормально, но следует обратить внимание);
- 6 — INFO (информационное сообщение);
- 7 —DEBUG (отложенная печать).
Коды уровней ошибок указываются после опции -p.
Запись логов в стандартный вывод
По умолчанию journalctl использует для вывода сообщений логов внешнюю утилиту less. В этом случае к ним невозможно применять стандартные утилиты для обработки текстовых данных (например, grep). Эта проблема легко решается: достаточно воспользоваться опцией −−no-pager, и все сообщения будут записываться в стандартный вывод:
$ journalctl --no-pager
После этого их можно будет передать другим утилитам для дальнейшей обработки или сохранить в текстовом файле.
Выбор формата вывода
C помощью опции -o можно преобразовывать данные логов в различные форматы, что облегчает их парсинг и дальнейшую обработку, например:
$ journalctl -u nginx.service -o json
{ "__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635", "__REALTIME_TIMESTAMP" : "1422990364739502", "__MONOTONIC_TIMESTAMP" : "27200938", "_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d", "PRIORITY" : "6", "_UID" : "0", "_GID" : "0", "_CAP_EFFECTIVE" : "3fffffffff", "_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee", "_HOSTNAME" : "desktop", "SYSLOG_FACILITY" : "3", "CODE_FILE" : "src/core/unit.c", "CODE_LINE" : "1402", "CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading", "SYSLOG_IDENTIFIER" : "systemd", "MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5", "_TRANSPORT" : "journal", "_PID" : "1", "_COMM" : "systemd", "_EXE" : "/usr/lib/systemd/systemd", "_CMDLINE" : "/usr/lib/systemd/systemd", "_SYSTEMD_CGROUP" : "/", "UNIT" : "nginx.service", "MESSAGE" : "Starting A high performance web server and a reverse proxy server...", "_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973" }
Объект json можно представить в более структурированном и человекочитаемом виде, указав формат json-pretty или json-sse:
$ journalctl -u nginx.service -o json-pretty
{
"__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635",
"__REALTIME_TIMESTAMP" : "1422990364739502",
"__MONOTONIC_TIMESTAMP" : "27200938",
"_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d",
"PRIORITY" : "6",
"_UID" : "0",
"_GID" : "0",
"_CAP_EFFECTIVE" : "3fffffffff",
"_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee",
"_HOSTNAME" : "desktop",
"SYSLOG_FACILITY" : "3",
"CODE_FILE" : "src/core/unit.c",
"CODE_LINE" : "1402",
"CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading",
"SYSLOG_IDENTIFIER" : "systemd",
"MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5",
"_TRANSPORT" : "journal",
"_PID" : "1",
"_COMM" : "systemd",
"_EXE" : "/usr/lib/systemd/systemd",
"_CMDLINE" : "/usr/lib/systemd/systemd",
"_SYSTEMD_CGROUP" : "/",
"UNIT" : "nginx.service",
"MESSAGE" : "Starting A high performance web server and a reverse proxy server...",
"_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973"
}
Помимо JSON данные логов могут быть преобразованы в следующие форматы:
- cat — только сообщения из логов без служебных полей;
- export — бинарный формат, подходит для экспорта или резервного копирования логов;
- short — формат вывода syslog;
- short-iso — формат вывода syslog с метками времени в формате ISO 8601;
- short-monotonic — формат вывода syslog c метками монотонного времени (monotonic timestamp);
- short-precise — формат вывода syslog с метками точного времени (время событий указывается с точностью до микросекунд);
- verbose — максимально подробный формат представления данных (включает даже те поля, которые в других форматах не отображаются).
Просмотр информации о недавних событиях
Опция -n используется для просмотра информации о недавних событиях в системе:
$ journalctl -n
По умолчанию на консоль выводится информация о последних 10 событиях. С опцией -n можно указать необходимое число событий:
$ journalctl -n 20
Просмотр логов в режиме реального времени
Сообщения из логов можно просматривать не только в виде сохранённых файлов, но и в режиме реального времени. Для этого используется опция -f:
$ journalctl -f
Управление логгированием
Определение текущего объёма логов
Со временем объём логов растёт, и они занимают всё больше места на жёстком диске. Узнать объём имеющихся на текущий момент логов можно с помощью команды:
$ journalctl --disk-usage
Journals take up 16.0M on disk.
Ротация логов
Настройка ротации логов осуществляется с помощью опций −−vacuum-size и −−vacuum-time.
Первая из них устанавливает предельно допустимый размер для хранимых на диске логов (в нашем примере — 1 ГБ):
$ sudo journalctl --vacuum-size=1G
Как только объём логов превысит указанную цифру, лишние файлы будут автоматические удалены.
Аналогичным образом работает опция −−vacuum-time. Она устанавливает для логов срок хранения, по истечении которого они будут автоматически удалены:
$ sudo journalctl --vacuum-time=1years
Настройка ротации логов в конфигурационном файле
Настройки ротации логов можно также прописать в конфигурационном файле /еtc/systemd/journald.conf, который включает в числе прочих следующие параметры:
- SystemMaxUse= максимальный объём, который логи могут занимать на диске;
- SystemKeepFree= объём свободного места, которое должно оставаться на диске после сохранения логов;
- SystemMaxFileSize= объём файла лога, по достижении которого он должен быть удален с диска;
- RuntimeMaxUse= максимальный объём, который логи могут занимать в файловой системе /run;
- RuntimeKeepFree= объём свободного места, которое должно оставаться в файловой системе /run после сохранения логов;
- RuntimeMaxFileSize= объём файла лога, по достижении которого он должен быть удален из файловой системы /run.
Централизованное хранение логов
Одной из самых распространённых задач в работе системного администратора является настройка сбора логов с нескольких машин с последующим помещением в централизованное хранилище.
В systemd предусмотрены специальные компоненты для решения этой задачи: systemd-journal-remote, systemd-journal-upload и systemd-journal-gatewayd.
С помощью команды systemd-journal-remote можно принимать логи с удалённых хостов и сохранять их (на каждом их этих хостов должен быть запущен демон systemd-journal-gatewayd), например:
$ systemd-journal-remote −−url https://some.host:19531/
В результате выполнения приведённой команды логи с хоста https://some.host/ будут сохранены в директории var/log/journal/some.host/remote-some~host.journal .
С помощью команды systemd-journal-remote можно также складывать имеющиеся на локальной машине логи в отдельную директорию, например:
$ journalctl -o export | systemd-journal-remote -o /tmp/dir -
Команда systemd-journal-upload используется для загрузки логов с локальной машины в удалённое хранилище:
$ systemd-journal-upload --url https://some.host:19531/
Как видно из приведённых примеров, «родные» утилиты systemd для поддержки централизованного логгирования просты и удобны в работе. Но они, к сожалению, пока что включены далеко не во все дистрибутивы, а только в Fedora и ArchLinux.
Пользователи других дистрибутивов пока что приходится передавать логи в syslog или rsyslog, которые затем пересылают их по сети. Ещё одно решение проблемы централизованного логгирования было предложено разработчиками утилиты journal2gelf, включённой в официальный репозиторий systemd: вывод journalсtl в формате JSON конвертируется в формат GELF, а затем передаётся приложению для сбора и анализа логов Graylog. Решение не очень удобное, но ничего лучше в текущей ситуации придумать нельзя. Остаётся только ждать, когда «родные» компоненты будут добавлены во все дистрибутивы.
Заключение
Как видно из проделанного рассмотрения, systemd journal представляет собой гибкий и удобный инструмент для сбора системных данных и данных приложений. Высокого уровня гибкости и удобства удалось добиться, во-первых, благодаря централизованному подходу к логгированию, а во-вторых — благодаря автоматической записи в логи подробных метаданных. С помощью journalctl можно просматривать логи, получая необходимую информацию для анализа работы и отладки различных системных компонентов.
Если у вас есть вопросы и дополнения — добро пожаловать в комментарии. Разговор о systemd и его компонентах будет продолжен в следующих публикациях.
The systemd
daemon uses a centralized logging system called a journal, which
is managed by the journald
daemon. This daemon collects all log entries
generated by the Linux kernel or any other systemd
unit service regardless of
their origin and stores them in a format that is easy to access and manipulate.
The journalctl
utility is provided for querying and filtering the data held
within the journal as written by the journald
service,
While diagnosing or troubleshooting an issue with the server or one of our
services, the first place to look is the log entries in the journal. Due to its
centralized nature, the journal could potentially contain thousands of log
entries that may not be relevant to our current problem. Therefore, it’s
necessary to filter out what we don’t need to quickly find the relevant
information that will help us solve the problem, and that’s what this tutorial
is all about.
🔭 Want to centralize and monitor your Linux logs?
Head over to Logtail and start ingesting your logs in 5 minutes.
Prerequisites
Before you proceed with this tutorial, you will need the following:
- A Linux server that includes a non-root user with
sudo
access. We tested all
the commands presented in this guide on an Ubuntu 20.04 server. - A basic understanding of how logging works in
Linux.
Step 1 — Permitting a user to view the system logs
By default, a user can only see log entries from systemd
services under the
user’s control. If you run the journalctl
command without any arguments, you
may see the following message at the top of the output:
Hint: You are currently not seeing messages from other users and the system.
Users in groups 'adm', 'systemd-journal' can see all messages.
Pass -q to turn off this notice.
. . .
This informs you that the output produced by the utility does not include
entries created by system services and those under other users’ control. The way
to ensure that you can view all log messages is by adding the user to an
existing group such as adm
or systemd-journal
.
Go ahead and add the current user to the systemd-journal
group using the
command below:
sudo usermod -a -G systemd-journal <user>
After logging out and logging back in again, you’ll be able to to see all the
available messages, and not just the ones that pertain to the current user.
Step 2 — Querying the journal with Journalctl
In this section, we will query the systemd
journal using journalctl
, and
view the results in various ways. Enter the command below to see all the logs
collected by the journald
daemon:
When used alone without any options, the journalctl
command will output all
the journal entries on the system and pipe them through a pager (usually
less
). You can also cause journalctl
to print its output directly to the
standard output instead of using a pager by including the --no-pager
flag.
This is useful if you want to process the data further with text processing
tools like grep
, awk
, or sed
, or redirect the output to a file.
The first line of the output is a header that describes the time range of the
displayed logs:
-- Logs begin at Fri 2022-02-11 15:34:17 UTC, end at Wed 2022-02-16 08:57:01 UTC. --
Below the header, you will see log entries generated by various programs in the
following format and sorted from oldest to newest:
Feb 16 08:59:57 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"devankoshal","facility":"ftp","hostname":"we.com","message":"Take a breath, let it go, walk away","msgid":"ID911","procid":1211,"severity":"debug","timestamp":"2022-0>
Feb 16 08:59:58 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"Karimmove","facility":"alert","hostname":"for.de","message":"Maybe we just shouldn't use computers","msgid":"ID528","procid":3542,"severity":"debug","timestamp":"2022>
Feb 16 08:59:59 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"jesseddy","facility":"authpriv","hostname":"some.net","message":"You're not gonna believe what just happened","msgid":"ID427","procid":7885,"severity":"alert","timest>
Feb 16 09:00:00 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"benefritz","facility":"daemon","hostname":"up.us","message":"We're gonna need a bigger boat","msgid":"ID220","procid":5116,"severity":"crit","timestamp":"2022-02-16T0>
Feb 16 09:00:01 ubuntu-2gb-nbg1-1 CRON[100444]: pam_unix(cron:session): session opened for user ayo by (uid=0)
Feb 16 09:00:01 ubuntu-2gb-nbg1-1 CRON[100445]: (ayo) CMD (/usr/sbin/logrotate /home/ayo/logrotate.conf --state /home/ayo/custom-state)
Feb 16 09:00:01 ubuntu-2gb-nbg1-1 CRON[100444]: pam_unix(cron:session): session closed for user ayo
Feb 16 09:00:01 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"benefritz","facility":"uucp","hostname":"make.de","message":"You're not gonna believe what just happened","msgid":"ID783","procid":6478,"severity":"debug","timestamp">
Feb 16 09:00:02 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"meln1ks","facility":"clockd","hostname":"for.net","message":"#hugops to everyone who has to deal with this","msgid":"ID114","procid":8519,"severity":"debug","timestam>
Feb 16 09:00:03 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"shaneIxD","facility":"cron","hostname":"make.org","message":"Maybe we just shouldn't use computers","msgid":"ID196","procid":2970,"severity":"err","timestamp":"2022-0>
Each entry starts with a timestamp, the hostname of the machine, the program
that generated the log entry, and its process id. The log message itself comes
afterward.
If you want to print only the last few log entries, you can use the -n
option,
which will restrict the printed entries to specified number:
journalctl -n 10 # print the last 10 entries
You can also view incoming log messages in real-time through the -f
flag,
which imitates tail -f
:
In later sections, we’ll look at more sophisticated ways of filtering the logs
produced by journalctl
so that we can find the information we’re looking for
quickly. Let’s discuss customizing the output of the journalctl
command first
though.
Step 3 — Customizing the log output format
When parsing the log entries produced by journalctl
, it may be useful to
change the format to an easy to parse format like JSON. This is possible by
specifying the json
format through the -o
option:
journalctl -o json -n 10 --no-pager
This yields the following output:
{"_SELINUX_CONTEXT":"unconfinedn","SYSLOG_FACILITY":"3","_SYSTEMD_SLICE":"system.slice","MESSAGE":"{"appname":"shaneIxD","facility":"mail","hostname":"make.com","message":"A bug was encountered but not in Vector, which doesn't have bugs","msgid":"ID598","procid":2005,"severity":"crit","timestamp":"2022-02-16T23:29:58.696Z","version":1}","_SYSTEMD_UNIT":"vector.service","_SYSTEMD_CGROUP":"/system.slice/vector.service","_HOSTNAME":"ubuntu-2gb-nbg1-1","SYSLOG_IDENTIFIER":"vector","_COMM":"vector","_SYSTEMD_INVOCATION_ID":"5435d275748449c58c051f7c6ecc2e8c","_PID":"74071","_MACHINE_ID":"cee31bed2e414d19ab394c074b55b354","_EXE":"/usr/bin/vector","__REALTIME_TIMESTAMP":"1645054198697037","_STREAM_ID":"a5e2ba59f2d34a829098f6f9db57be9c","_BOOT_ID":"06a58ed252614238b0d09d15161688ed","__MONOTONIC_TIMESTAMP":"481325512974","_TRANSPORT":"stdout","_GID":"997","_UID":"997","PRIORITY":"6","_CAP_EFFECTIVE":"400","_CMDLINE":"/usr/bin/vector","__CURSOR":"s=d96f9da5333a4e1d8394272215ea1917;i=2d710c;b=06a58ed252614238b0d09d15161688ed;m=70113c790e;t=5d82b07264c4d;x=bb9760a144a3a0d1"}
. . .
Notice how detailed this output is compared to the default and how more
information is contained therein. You can also specify json-pretty
instead of
json
:
journalctl -o json-pretty -n 10 --no-pager
This makes the command output more readable at the cost of screen real-estate:
{
"_PID" : "74071",
"_SYSTEMD_INVOCATION_ID" : "5435d275748449c58c051f7c6ecc2e8c",
"_MACHINE_ID" : "cee31bed2e414d19ab394c074b55b354",
"_SELINUX_CONTEXT" : "unconfinedn",
"PRIORITY" : "6",
"__MONOTONIC_TIMESTAMP" : "481505512370",
"_HOSTNAME" : "ubuntu-2gb-nbg1-1",
"_SYSTEMD_SLICE" : "system.slice",
"SYSLOG_FACILITY" : "3",
"MESSAGE" : "{"appname":"benefritz","facility":"lpr","hostname":"we.com","message":"There's a breach in the warp core, captain","msgid":"ID448","procid":8376,"severity":"crit","timestamp":"2022-02-16T23:32:58.695Z","version":2}",
"SYSLOG_IDENTIFIER" : "vector",
"_SYSTEMD_CGROUP" : "/system.slice/vector.service",
"_UID" : "997",
"_CAP_EFFECTIVE" : "400",
"_STREAM_ID" : "a5e2ba59f2d34a829098f6f9db57be9c",
"_SYSTEMD_UNIT" : "vector.service",
"__CURSOR" : "s=d96f9da5333a4e1d8394272215ea1917;i=2d71f5;b=06a58ed252614238b0d09d15161688ed;m=701bf70bb2;t=5d82b11e0def1;x=529c820dc1c2952c",
"_GID" : "997",
"__REALTIME_TIMESTAMP" : "1645054378696433",
"_COMM" : "vector",
"_EXE" : "/usr/bin/vector",
"_TRANSPORT" : "stdout",
"_CMDLINE" : "/usr/bin/vector",
"_BOOT_ID" : "06a58ed252614238b0d09d15161688ed"
}
Here’s a few of all available formats that control the output produced by
journalctl
. You can examine the
complete list here.
cat
: includes the log message only.short
: the default output format.json
: JSON-formatted output containing all available journal fields.json-pretty
: prettified JSON output for better readability.verbose
: displays the full log entry with all fields.
Now that we have a handle on how to present the journalctl
output in different
ways, let’s look at a few ways to narrow down the entries produced by the
utility.
Step 4 — Filtering the journal by boot session
One of the most common ways to filter the journalctl
output is by only
including messages that were logged after a specific system boot. For example,
you can view all the logs collected since the most recent boot by executing
journalctl
with -b
flag:
The program should display an output similar to the one shown below:
-- Logs begin at Fri 2022-02-11 15:34:17 UTC, end at Wed 2022-02-16 09:24:09 UTC. --
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Stopped target Main User Target.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Stopped target Basic System.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Stopped target Paths.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Stopped target Sockets.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Stopped target Timers.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: dbus.socket: Succeeded.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Closed D-Bus User Message Bus Socket.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: dirmngr.socket: Succeeded.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Closed GnuPG network certificate management daemon.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: gpg-agent-browser.socket: Succeeded.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Closed GnuPG cryptographic agent and passphrase cache (access for web browsers).
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: gpg-agent-extra.socket: Succeeded.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Closed GnuPG cryptographic agent and passphrase cache (restricted).
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: gpg-agent-ssh.socket: Succeeded.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Closed GnuPG cryptographic agent (ssh-agent emulation).
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: gpg-agent.socket: Succeeded.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: Closed GnuPG cryptographic agent and passphrase cache.
Feb 11 15:34:17 ubuntu-2gb-nbg1-1 systemd[1279]: pk-debconf-helper.socket: Succeeded.
. . .
This output shows all records in chronological order as before. Before seeing
application logs, you will observe that the oldest records show very low-level
kernel information about the system boot processes.
If you want to print the logs that pertain to a boot session other than the last
one, you can list all boots that journald
knows about by executing
journalctl
with parameter --list-boots
:
You’ll see the program’s output appear on the screen:
-3 9a8ebc63800e4b488b8b0fe90991600c Thu 2021-03-25 18:44:20 UTC—Thu 2021-03-25 18:57:41 UTC
-2 8a0a7c2d722d49f3ba3f411cf2344bb8 Thu 2021-03-25 18:58:11 UTC—Wed 2021-04-14 16:00:31 UTC
-1 0f419686d8744067acd4e7ab962a280b Wed 2021-04-14 16:01:14 UTC—Thu 2021-04-15 14:02:09 UTC
0 dbf7a43ac05f45e39be23091acf434bc Thu 2021-04-15 14:02:32 UTC—Thu 2021-04-15 18:00:31 UTC
The output shows all the available system boots with their offset number, boot
ID (an hexadecimal number), and time range. The value from the offset column can
be used as shown below:
journalctl -b 0 # same as journalctl -b
$ journalctl -b -1 # output logs from the previous boot session
You can also use the boot ID as shown below:
journalctl -b 0f419686d8744067acd4e7ab962a280b
This will show all the log entries that were collected within the boot session
from 2021-04-14 16:01:14
to 2021-04-15 14:02:09
.
When dealing with servers that do not often reboot, filtering the logs by system
boot may not be helpful as the current boot session may be the only one
available. Therefore, in the next section, we’ll consider a more granular way to
restrict the log entries outputted by journalctl
.
Step 5 — Showing logs within a time range
A typical way to filter system logs is by querying for those that fall before,
after, or between a given period. You can use the --since
flag to specify a
lower time limit and the --until
for an upper limit. Both flags accepts a
timestamp value that follows the systemd.time
specification.
The following are examples of valid arguments to --since
and -until
.
2021-11-23 23:02:15
2021-05-04
12:00
5 hour ago
, or32 min ago
yesterday
,today
,now
Let’s go ahead and view today’s records using the command below:
journalctl --since 'today'
You’ll see the program’s output appear on the screen:
-- Logs begin at Fri 2022-02-11 15:34:17 UTC, end at Wed 2022-02-16 21:33:52 UTC. --
Feb 16 00:00:00 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"ahmadajmi","facility":"local4","hostname":"we.com","message":"#hugops to everyone who has to deal with this","msgid":"ID844","procid":113,"severity":"alert","timestam>
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 systemd[1]: Starting Rotate log files...
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 systemd[1]: Starting Daily man-db regeneration...
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 CRON[79633]: pam_unix(cron:session): session opened for user ayo by (uid=0)
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 CRON[79641]: (ayo) CMD (/usr/sbin/logrotate /home/ayo/logrotate.conf --state /home/ayo/custom-state)
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 CRON[79633]: pam_unix(cron:session): session closed for user ayo
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 systemd[1]: logrotate.service: Succeeded.
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 systemd[1]: Finished Rotate log files.
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"meln1ks","facility":"ntp","hostname":"make.net","message":"You're not gonna believe what just happened","msgid":"ID477","procid":6062,"severity":"notice","timestamp":>
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 systemd[1]: man-db.service: Succeeded.
Feb 16 00:00:01 ubuntu-2gb-nbg1-1 systemd[1]: Finished Daily man-db regeneration.
Feb 16 00:00:02 ubuntu-2gb-nbg1-1 vector[74071]: {"appname":"shaneIxD","facility":"daemon","hostname":"names.com","message":"Take a breath, let it go, walk away","msgid":"ID74","procid":1031,"severity":"notice","timestamp":"202>
The output may show a lot of records, but you’ll observe that they were all
recorded on the current day. You can also filter logs that fall on a specific
date or between specific dates:
journalctl --since '2022-02-16 21:00:00' --until '2022-02-16 22:00:00'
As you can see, journalctl
provides great flexibility when it comes to
filtering records by time. However, the log entries still contain records from
several different services. If you’re only interested in a records from a
specific application, filtering by time only will still yield irrelevant
messages. In the next section, we’ll consider how to restrict the journalctl
output to entries produced by a specific systemd
service.
Step 6 — Filtering journal entries by service
If you are interested only in log entries related to a specific systemd
unit
service, you can pass the service name to the -u
flag. For example, let’s view
the last 10 log messages produced by the sshd
service using the command shown
below:
journalctl -u sshd.service -n 10
You’ll see the program’s output appear on the screen:
-- Logs begin at Fri 2022-02-11 15:34:17 UTC, end at Wed 2022-02-16 22:03:52 UTC. --
Feb 16 21:56:48 ubuntu-2gb-nbg1-1 sshd[61254]: Received disconnect from 122.194.229.45 port 19218:11: [preauth]
Feb 16 21:56:48 ubuntu-2gb-nbg1-1 sshd[61254]: Disconnected from 122.194.229.45 port 19218 [preauth]
Feb 16 21:57:39 ubuntu-2gb-nbg1-1 sshd[61258]: Invalid user test3 from 45.112.242.67 port 55536
Feb 16 21:57:39 ubuntu-2gb-nbg1-1 sshd[61258]: Received disconnect from 45.112.242.67 port 55536:11: Bye Bye [preauth]
Feb 16 21:57:39 ubuntu-2gb-nbg1-1 sshd[61258]: Disconnected from invalid user test3 45.112.242.67 port 55536 [preauth]
Feb 16 21:57:52 ubuntu-2gb-nbg1-1 sshd[61260]: Invalid user wedding from 51.140.185.84 port 51118
Feb 16 21:57:52 ubuntu-2gb-nbg1-1 sshd[61260]: Received disconnect from 51.140.185.84 port 51118:11: Bye Bye [preauth]
Feb 16 21:57:52 ubuntu-2gb-nbg1-1 sshd[61260]: Disconnected from invalid user wedding 51.140.185.84 port 51118 [preauth]
Feb 16 21:59:41 ubuntu-2gb-nbg1-1 sshd[61265]: Accepted publickey for ayo from 217.138.222.109 port 59800 ssh2: RSA SHA256:8Gdo7Q35uybWwTaGAoWrQXowqn0MEGaErerTlpR7nTM
Feb 16 21:59:41 ubuntu-2gb-nbg1-1 sshd[61265]: pam_unix(sshd:session): session opened for user ayo(uid=1000) by (uid=0)
From the output above, you can observe that only the records that pertain to
sshd
are displayed. If you need to view the logs for more than one service,
you can repeat the -u
flag in the command with the names of different
services.
journalctl -u rsyslog.service -u nginx.service --since today
The entries produced from both services will be merged and presented in
chronological order. You can also use the --since
and --until
flags to
narrow down the results further as you see fit.
Step 7 — Filtering journal entries by priority level
Each journal record has a well-defined structure that also includes message
priority. The journalctl
command allows filtering records by message priority,
which are the same as the standard syslog
priority levels (listed in
descending order):
{
emerg: 0,
alert: 1,
crit: 2,
error: 3,
warning: 4,
notice: 5,
info: 6,
debug: 7
}
Here’s an explanation of the levels above:
emerg
: the system is unusable.alert
: action must be taken immediately.crit
: critical conditions.err
: error conditions.warning
: warning conditions.notice
: normal, but significant condition.info
: informational message.debug
: messages that are useful for debugging.
You can specify the priority name or its corresponding number value when
filtering log records with journalctl
by using the -p
option:
journalctl -p err
# or
$ journalctl -p 3
The command above will display all messages prioritized at err
level or above.
This means that the output will not contain messages logged at warning
level
or below.
-- Logs begin at Fri 2022-02-11 15:34:17 UTC, end at Wed 2022-02-16 22:58:21 UTC. --
Feb 11 15:41:23 ubuntu-2gb-nbg1-1 sudo[909]: pam_unix(sudo:auth): auth could not identify password for [ayo]
Feb 11 15:41:23 ubuntu-2gb-nbg1-1 sudo[909]: ayo : user NOT in sudoers ; TTY=pts/0 ; PWD=/home/ayo ; USER=root ; COMMAND=/usr/bin/dnf install fish
Feb 11 15:41:34 ubuntu-2gb-nbg1-1 sudo[911]: ayo : user NOT in sudoers ; TTY=pts/0 ; PWD=/home/ayo ; USER=root ; COMMAND=/usr/bin/dnf update
Feb 11 15:44:31 ubuntu-2gb-nbg1-1 sshd[976]: fatal: Timeout before authentication for 1.15.86.71 port 41058
Feb 11 20:38:11 ubuntu-2gb-nbg1-1 sshd[3300]: error: kex_exchange_identification: Connection closed by remote host
Feb 11 20:58:23 ubuntu-2gb-nbg1-1 sshd[3348]: error: kex_exchange_identification: Connection closed by remote host
Feb 12 00:44:08 ubuntu-2gb-nbg1-1 sshd[4536]: error: kex_exchange_identification: Connection closed by remote host
Feb 12 01:22:43 ubuntu-2gb-nbg1-1 sshd[4622]: error: kex_exchange_identification: Connection closed by remote host
. . .
This feature makes it easy to remove irrelevant information when troubleshooting
a problem so that the higher priority messages can take center stage.
Step 8 — Cleaning up old journal entries
The journalctl
command also provides control over how much space is used up by
the journal, and when to clean up older entries. You can use the --disk-usage
flag to discover how much is currently being used up:
You should see the following output:
Archived and active journals take up 1.8G in the file system.
If you want to shrink your journal to a certain size, you can use the
--vacuum-size
option as shown below:
sudo journalctl --vacuum-size=500M # shrink journal to 500 MB.
You’ll see the program’s output appear on the screen:
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-00000000001705f4-0005d7c8815c6001.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-000000000018a118-0005d7ccffbf428b.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-00000000001a39bc-0005d7d1621e9d0e.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-00000000001bd232-0005d7d5977c6dd9.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-00000000001d6237-0005d7d9614516c8.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-00000000001ef1f4-0005d7dd2e4431c9.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-00000000002081d7-0005d7e0f8261d1a.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-000000000022130a-0005d7e4c5032aa2.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-000000000023ac43-0005d7e9129c10c1.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-000000000025457d-0005d7ecc6945d7e.journal (128.0M).
Deleted archived journal /var/log/journal/cee31bed2e414d19ab394c074b55b354/system@d96f9da5333a4e1d8394272215ea1917-000000000026d5ce-0005d7f0c66f8cfe.journal (128.0M).
Vacuuming done, freed 1.3G of archived journals from /var/log/journal/cee31bed2e414d19ab394c074b55b354.
Vacuuming done, freed 0B of archived journals from /run/log/journal.
Vacuuming done, freed 0B of archived journals from /var/log/journal.
As you can see, the journal was shrunk to 500 MB after log entries totalling 1.3
GB in size were deleted from the archive. An alternative to --vacuum-size
is
the --vacuum-time
option which allows you to delete logs older than a certain
period of time.
For example, you can delete the entries that were created more than one month
ago through the command below:
sudo journalctl --vacuum-time=1month
You can also limit the storage space that the journal takes up by editing the
following options
in the /etc/systemd/journald.conf
file:
SystemMaxUse=
andRuntimeMaxUse=
: the maximum amount of space that the
journal should take up in a persistent storage (/var/log/journal
) and
in-memory storage (/run/log/journal
) respectively.SystemKeepFree=
andRuntimeKeepFree=
: defines the percentage of disk space
that should be kept free for other uses.SystemMaxFileSize=
andRuntimeMaxFileSize=
: controls how large journal
entries should grow before being rotated.SystemMaxFiles=
andRuntimeMaxFiles=
: controls the maximum number of
journal files to keep.
Conclusion
In this article, you learned about the systemd journal and how to manage it
through the journalctl
command. We started by discussing what the journal is
for, and then described how to view and filter its entries in various ways. To
learn more about the systemd journal and the journalctl
command, consult the
official documentation
or type man journalctl
in your terminal.
Thanks for reading, and happy logging!
Centralize all your logs into one place.
Analyze, correlate and filter logs with SQL.
Create actionable
dashboards.
Share and comment with built-in collaboration.
Got an article suggestion?
Let us know
Next article
How to Set Up Centralized Logging on Linux with Rsyslog
Learn how to set up a centralized logging on linux with rsyslog
→
Explore more
Learn everything you want to know about logging. Go from basics to best practices in no time.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
https://ru.opensuse.org/SDB:Systemd#systemd-journalctl:
Начиная с версии v38+ systemd имеет собственную систему регистрации событий, которая по умолчанию включена в дистрибутив openSUSE 12.2+. systemd-journalctl является неотъемлемой частью systemd и не может использоваться отдельно. Журналы данного инструмента хранятся в бинарном виде в /var/log/journal, что исключает возможность просмотра содержимого данных файлов стандартными утилитами обработки текстовых данных. При вызове инструмента без параметров покажет все содержимое журнала аналогичного классической системе лог-файлов syslog ( /var/log/messages )
Подробное описание работы с журналом, см (англ)
man systemd-journald man journalctl
Основные сведения
Ключи journalctl
- Получить актуальные ключи команды:
- Чтение всех логов:
- Логи с момента запуска системы:
- Если был крах системы, можно ввести параметр -1 и посмотреть логи с предыдущего запуска системы (-2 логи сеанса за два сеанса до текущего и т.д.) [1]:
- Показывать записи журнала с момента запуска системы с расшифровкой ошибок:
- Показать самые последние записи журнала, и продолжать печатать новые записи, при добавлении их в журнал:
Вывод лога в текстовый файл
Если вам нужно вывести лог в текстовый файл (например, чтобы сообщить разработчикам об ошибке), используйте конструкцию
'команда' > 'путь к текстовому файлу'
Пример:
journalctl -b > /home/user/debug.log
Фильтрация по дате и времени
Для фильтрации по дате и времени важны два ключа
- —since — вывод от такого-то момента времени
- —until — вывод до такого-то момента времени
в качестве значений для этих ключей могут использоваться:
— Формат YYYY-MM-DD HH:MM:SS
journalctl --since "2017-05-05 00:01" --until "2017-05-06 01:40"
— Слова «yesterday», «today», «tomorrow», «now»:
journalctl --since "yesterday" --until "2017-05-06 01:40"
— Удобочитаемые выражения вида:
journalctl --since "10 hours ago" journalctl --since "1 minute ago" journalctl --since "50 minute ago" --until "5 minute ago"
Примеры
- Показать все сообщения за последние 20 минут:
journalctl --since "20 min ago"
- Просмотреть все сообщения начиная с 20 июля 2015 года 17:15:
journalctl --since "2015-07-20 17:15:00"
- Просмотреть все сообщения начиная со вчерашнего дня:
journalctl --since "yesterday"
- Просмотреть все сообщения с 9:00 до настоящего времени:
journalctl --since "09:00" --until "now"
- Просмотреть все сообщения с 9:00 до прошлого часа:
journalctl --since "10:00" --until "1 hour ago"
Фильтрация по другим параметрам
- Показывать в реальном времени все записи, независимо от их размера и кодировки:
- Просмотр сообщений ядра [1]:
- Все сообщение конкретной утилиты, например, systemd:
journalctl /usr/lib/systemd/systemd
- Все сообщения конкретного процесса:
- Все сообщения конкретного приложения или службы:
- Все сообщения процессов, запущенных от имени конкретного пользователя:
Журнал
- Журнал хранится в двоичном формате, поэтому в окружении, где не установлен systemd, его логи можно посмотреть с помощью команды strings:
strings /mnt/arch/var/log/journal/af4967d77fba44c6b093d0e9862f6ddd/system.journal | grep -i сообщение
- Если же имеется файл журнала, например, с другого компьютера и systemd установлен (должно быть достаточно пакета journalctl из Sisyphus), то посмотреть его содержимое проще:
из директории
journalctl -D /mnt/arch/var/log/journal/af4967d77fba44c6b093d0e9862f6ddd
из файла
journalctl --file /mnt/arch/var/log/journal/af4967d77fba44c6b093d0e9862f6ddd/system.journal
Недавние события
- Просмотр информации о недавних событиях
- По умолчанию на консоль выводится информация о последних 10 событиях. С опцией -n можно указать необходимое число событий:
Анализ этапа загрузки
Для анализа этапа инициализации системы используется утилита systemd-analyze. Для установки делаем от root:
apt-get install systemd-analyze
Выявляем самые медленные процессы (от пользователя):
Выводим график загрузки процессов в векторный рисунок:
systemd-analyze plot > file.svg
Основные настройки
Файл настройки находится в /etc/systemd/journald.conf и состоит из следующих секций:
- Storage= Указывает, где хранить журнал. Доступны следующие параметры:
- volatile Журнал хранится в оперативной памяти, т.е. в каталоге /run/log/journal.
- persistent Данные хранятся на диске, т.е. в каталоге /var/log/journal
- auto используется по-умолчанию
- none Журнал не ведётся
- Compress= Принимает значения «yes» или «no». Если включена (по-умолчанию) сообщения перед записью в журнал, будут сжиматься.
- Seal= Принимает значения «yes» или «no». Если включена (по-умолчанию) будет включена защита Forward Secure Sealing (FSS), которая позволяет накладывать криптографические отпечатки на журнал системных логов.
- SplitMode= Определяет доступ к журналу пользователям. Доступны следующие параметры:
- uid Все пользователи получают доступ к чтению системного журнала. Используется по-умочанию.
- login Каждый пользователь может читать только сообщения, относящиеся к его сеансу.
- none Пользователи не имеют доступа к системному журналу.
- SyncIntervalSec= Таймаут, после которого происходит синхронизация и запись журнала на диск. Относится только к уровням ERR, WARNING, NOTICE, INFO, DEBUG. Сообщения уровня CRIT, ALERT, EMERG записываются сразу на диск.
- RateLimitInterval= и RateLimitBurst= Настройки ограничения скорости генерации сообщений для каждой службы. Если в интервале времени, определяемого RateLimitInterval=, больше сообщений, чем указано в RateLimitBurst= регистрируются службой, все дальнейшие сообщения в интервале отбрасываются, пока интервал не закончится.При этом генерируется сообщение о количестве отброшенных сообщений. По умолчанию 1000 сообщений за 30 секунд. Единицы измерения: «s», «min», «h», «ms», «us». Чтобы выключить ограничение скорости, установите значения в 0.
- MaxRetentionSec= Максимальное время хранения записей журнала. Единицы измерения: year, month, week, day, h или m
- MaxFileSec= Максимальное время хранения записей в одном файле журнала, после которого он переводится в следующий.
- ForwardToSyslog=, ForwardToKMsg=, ForwardToConsole=, ForwardToWall= Определяют куда направлять сообщения: в традиционный системный журнал Syslog, в буфер журнала ядра (kmsg), на системную консоль, или на стену, чтобы было видно всем зарегистрированным пользователям. Эти опции принимают логические аргументы. Если переадресация на Syslog включен, но Syslog демон не работает, соответствующий параметр не имеет никакого эффекта. По умолчанию, только стена включена. Эти параметры могут быть переопределены во время загрузки с параметрами командной строки ядра systemd.journald.forward_to_syslog =, systemd.journald.forward_to_kmsg =, systemd.journald.forward_to_console = и systemd.journald.forward_to_wall =. При пересылке в консоль, должен быть установлен TTYPath =, как будет описано ниже.
- TTYPath= Назначает консоль TTY, для вывода сообщений, если установлен параметр ForwardToConsole=yes. По-умолчанию, используется /dev/console. Для того, чтобы вывести на 12 консоль, устанавливаем TTYPath=/dev/tty12. Для того, чтобы вывести на последовательный порт, устанавливаем TTYPath=/dev/ttySX, где X номер com-порта.
- MaxLevelStore=, MaxLevelSyslog=, MaxLevelKMsg=, MaxLevelConsole=, MaxLevelWall= Определяет максимальный уровень сообщений который сохраняется в журнал, выводится на традиционный системный журнал Syslog, буфер журнала ядра (kmsg), консоль или стену. Значения: emerg, alert, crit, err, warning, notice, info, debug или цифры от 0 до 7 (соответствуют уровням).
Управление логированием
- Определение текущего объёма логов
Со временем объём логов растёт, и они занимают всё больше места на жёстком диске. Узнать объём имеющихся на текущий момент логов можно с помощью команды:
- Ротация логов
Настройка ротации логов осуществляется с помощью опций −−vacuum-size и −−vacuum-time.
Первая из них устанавливает предельно допустимый размер для хранимых на диске логов (в нашем примере — 1 ГБ):
journalctl --vacuum-size=1G
Как только объём логов превысит указанную цифру, лишние файлы будут автоматические удалены.
Аналогичным образом работает опция −−vacuum-time. Она устанавливает для логов срок хранения, по истечении которого они будут автоматически удалены:
journalctl --vacuum-time=1years
- Настройка ротации в конфигурационном файле. Настройки ротации логов можно также прописать в конфигурационном файле /еtc/systemd/journald.conf, который включает в числе прочих следующие параметры:
- SystemMaxUse= — максимальный объём, который логи могут занимать на диске;
- SystemKeepFree= — объём свободного места, которое должно оставаться на диске после сохранения логов;
- SystemMaxFileSize= — объём файла лога, по достижении которого он должен быть удален с диска;
- RuntimeMaxUse= — максимальный объём, который логи могут занимать в файловой системе /run;
- RuntimeKeepFree= — объём свободного места, которое должно оставаться в файловой системе /run после сохранения логов;
- RuntimeMaxFileSize= — объём файла лога, по достижении которого он должен быть удален из файловой системы /run.
Единицы измерения: K, M, G, T, P, E.
Возврат syslog
Допускается либо параллельное ведение журналов в syslog, либо полное переключение на него. За это отвечают параметры Storage и ForwardToSyslog в /etc/systemd/journald.conf:
[Journal] Storage=none ForwardToSyslog=yes
После этого надо установить logrotate и выбрать один из вариантов syslog.
При этом следует иметь ввиду это: Compatibility with classic syslog implementations is provided, via a socket /run/systemd/journal/syslog, to which all messages are forwarded, regardless whether they came in via /dev/log, the journal native protocol or any other source. To make your syslog implementaiton work with this make sure that it binds to that socket instead of /dev/log which is now systemd-journal property.
syslog-ng
Начиная со сборки 3.24.1-alt1 следует установить пакет syslog-ng-journal: altbug:36454.
rsyslog
Установить пакет rsyslog-classic.
Запись в журнал из скрипта
echo "MESSAGE" | systemd-cat -t myunit
где myunit — имя юнита.
Ссылки
- Описание демона systemd-journalctl На Wiki OpenSuse
- Systemd
- Статья на Хабрахабр «Управление логгированием в systemd»
- Улучшаем Systemd
Примечания :
- ↑ 1,0 1,1 Работает пока только в Сизифе, уточняйте через journalctl —help
Выше мы узнали о некоторых способах фильтрации данных журнала с использованием временных ограничений. В этом разделе мы обсудим, как фильтровать, основываясь на том, какие услуги или компоненты вас интересуют. Журналsystemd
предоставляет множество способов сделать это.
По подразделению
Возможно, самый полезный способ фильтрации — по интересующему вас устройству. Мы можем использовать опцию-u
для фильтрации таким образом.
Например, чтобы увидеть все журналы из модуля Nginx в нашей системе, мы можем набрать:
journalctl -u nginx.service
Как правило, вы, вероятно, захотите отфильтровать по времени, чтобы отобразить интересующие вас строки. Например, чтобы проверить, как служба работает сегодня, вы можете набрать:
journalctl -u nginx.service --since today
Этот тип фокуса становится чрезвычайно полезным, когда вы пользуетесь способностью журнала чередовать записи из разных блоков. Например, если ваш процесс Nginx подключен к модулю PHP-FPM для обработки динамического содержимого, вы можете объединить записи обоих в хронологическом порядке, указав оба модуля:
journalctl -u nginx.service -u php-fpm.service --since today
Это может упростить обнаружение взаимодействия между различными программами и системами отладки, а не отдельными процессами.
По процессу, пользователю или идентификатору группы
Некоторые службы порождают множество дочерних процессов для выполнения работы. Если вы нашли точный PID процесса, который вас интересует, вы также можете отфильтровать его.
Для этого мы можем фильтровать, указав поле_PID
. Например, если интересующий нас PID — 8088, мы могли бы набрать:
В других случаях вы можете захотеть показать все записи, зарегистрированные от определенного пользователя или группы. Это можно сделать с помощью фильтров_UID
или_GID
. Например, если ваш веб-сервер работает под пользователемwww-data
, вы можете найти идентификатор пользователя, набрав:
После этого вы можете использовать идентификатор, который был возвращен для фильтрации результатов журнала:
journalctl _UID=33 --since today
Журналsystemd
имеет множество полей, которые можно использовать для фильтрации. Некоторые из них передаются из процесса, который регистрируется, а некоторые применяютсяjournald
, используя информацию, которую он собирает из системы во время журнала.
Верхнее подчеркивание указывает, что поле_PID
относится к последнему типу. Журнал автоматически записывает и индексирует PID процесса, который регистрируется для последующей фильтрации. Вы можете узнать обо всех доступных полях журнала, набрав:
man systemd.journal-fields
Мы будем обсуждать некоторые из них в этом руководстве. Сейчас же мы рассмотрим еще одну полезную опцию, связанную с фильтрацией по этим полям. Параметр-F
может использоваться для отображения всех доступных значений для данного поля журнала.
Например, чтобы узнать, для каких идентификаторов групп есть записи в журналеsystemd
, вы можете ввести:
32
99
102
133
81
84
100
0
124
87
Это покажет вам все значения, которые журнал сохранил для поля идентификатора группы. Это может помочь вам построить ваши фильтры.
По пути компонента
Мы также можем отфильтровать, указав путь.
Если путь ведет к исполняемому файлу,journalctl
отобразит все записи, которые включают данный исполняемый файл. Например, чтобы найти те записи, которые включают исполняемый файлbash
, вы можете ввести:
Обычно, если модуль доступен для исполняемого файла, этот метод является более чистым и предоставляет лучшую информацию (записи из связанных дочерних процессов и т. Д.). Иногда, однако, это невозможно.
Отображение сообщений ядра
Сообщения ядра, которые обычно находятся в выводеdmesg
, также могут быть получены из журнала.
Чтобы отображать только эти сообщения, мы можем добавить к нашей команде флаги-k
или--dmesg
:
По умолчанию это будет отображать сообщения ядра от текущей загрузки. Вы можете указать альтернативную загрузку, используя обычные флаги выбора загрузки, которые обсуждались ранее. Например, чтобы получить сообщения от пяти загрузок назад, вы можете набрать:
По приоритету
Один фильтр, который часто интересует системных администраторов, — это приоритет сообщений. Хотя часто полезно регистрировать информацию на очень многословном уровне, при фактическом переваривании доступной информации журналы с низким приоритетом могут отвлекать и сбивать с толку.
Вы можете использоватьjournalctl
для отображения только сообщений с указанным приоритетом или выше, используя опцию-p
. Это позволяет вам отфильтровывать сообщения с более низким приоритетом.
Например, чтобы показать только записи, зарегистрированные с уровнем ошибки или выше, вы можете набрать:
Это покажет вам все сообщения, помеченные как ошибки, критические, оповещения или чрезвычайные ситуации. В журнале реализованы стандартные уровни сообщенийsyslog
. Вы можете использовать либо имя приоритета, либо его соответствующее числовое значение. В порядке наивысшего приоритета это:
-
0: emerg
-
1: оповещение
-
2: крит
-
3: ошибка
-
4: предупреждение
-
5: уведомление
-
6: информация
-
7: отладка
Приведенные выше числа или имена могут использоваться как синонимы с опцией-p
. При выборе приоритета будут отображаться сообщения, отмеченные на указанном уровне, и те, которые находятся над ним.
Problem determination can be as much an art as a science, and sometimes, it seems even a little magic can be useful. Everyone has encountered situations where a reported failure could not be reproduced, which is always frustrating for both the user and the system administrator. Even home appliances and automobiles can be obstinate and refuse to fail when the service person shows up.
Anthropomorphism aside, sysadmins have some tools that can show what has been happening in their Linux computers with varying degrees of granularity. There are tools, like top, htop, glances, sar, iotop, tcpdump, traceroute, mtr, iptraf-ng, df, du, and many more, all of which can display a host’s current state, and several of which can produce logs of various levels of detail.
While these tools can be used to find ongoing problems, they are not particularly helpful for transient problems or those with no directly observable symptoms—not observable, at least, until some major and possibly catastrophic problem occurs.
An important tool I use for problem determination is the system logs—and with systemd, the system journals. The systemd journal is always one of the first tools I turn to when solving a problem, especially the problems that don’t seem to happen when I am watching. It took me a long time at the beginning of my sysadmin career to realize the wealth of information in the log files, and this discovery greatly improved my speed in resolving problems.
You have already seen some uses of the journalctl
command in many of the previous articles in this series. In this article, I will explore some details about the systemd journal, how it works, and ways to use journalctl
to locate and identify problems.
About journals
The purpose of any log or journal is to maintain a time-sequenced history of the normal activities of the services and programs that run on a host and to record any errors or warning messages that occur. The log messages used to be maintained in separate files in /var/log
, usually one file for the kernel and separate ones for most of the services running on the host. Unfortunately, the large number of log files could spread out necessary information and delay the discovery of a problem’s root cause. This could be especially time-consuming when you’re trying to determine what was happening in a system when an error occurred.
The old /var/log/dmesg
file was usually used for the kernel, but that file was discontinued several years ago in favor of using the dmesg
command to display the same information and integrating those messages (and more) into the /var/log/messages
file. This merger of other logs into the messages
file helped speed problem determination by keeping much of the data in one file, but there were still many services whose logs were not integrated into the more central messages
file.
The systemd journal is designed to collect all messages into a single, unified structure that can show a complete picture of everything that happened in a system at and around a specific time or event. Because the events, regardless of the source, are in one place and in time sequence, it is possible to see at a glance everything happening at a specific point or range of times. In my opinion, this is one of the main benefits of systemd journaling.
About the systemd journal
The systemd journaling service is implemented by the systemd-journald
daemon. According to the systemd-journald
man page:
systemd-journald
is a system service that collects and stores logging data. It creates and maintains structured, indexed journals based on logging information that is received from a variety of sources:
- Kernel log messages, via
kmsg
- Simple system log messages, via the
libc syslog(3)
call- Structured system log messages via the native Journal API, see
sd_journal_print(3)
- Standard output and standard error of service units. For further details see below.
- Audit records, originating from the kernel audit subsystem
The daemon will implicitly collect numerous metadata fields for each log messages in a secure and unfakeable way. See
systemd.journal-fields(7)
for more information about the collected metadata.Log data collected by the journal is primarily text-based but can also include binary data where necessary. Individual fields making up a log record stored in the journal may be up to 2^64-1 bytes in size.
Configuration changes
The systemd journal daemon can be configured using the /etc/systemd/journald.conf
file. For many hosts, this file does not need any changes because the defaults are quite reasonable. Look at your journald.conf
file now, if you have not already.
The most common configuration changes you might consider would specify the maximum journal file size, the number of older journal files, and the maximum file-retention times. The primary reason to make those changes would be to reduce the storage space used by the journal if you have a small storage device. In a mission-critical environment, you may also want to reduce the amount of time between syncing journal data stored in RAM memory to the storage device.
The journald.conf
man page has more details.
Controversies about the data format
One of the controversies surrounding systemd is the binary format in which the journal contents are stored. Some arguments against systemd are based on the systemd journal being stored in a binary format. This would seem to be contrary to the Unix/Linux philosophy to use ASCII text for data, which is one argument people use to justify their dislike of systemd. For example, Doug McIlroy, the inventor of the pipes, said:
«This is the Unix Philosophy: Write programs that do one thing well. Write programs to work together. Write programs to handle text steams, because that is a universal interface.» —Doug McIlroy, quoted in Eric S. Raymond’s book The Art of Unix Programming
However, these arguments seem to be based on at least a partial misconception because the man page clearly states that the data «is primarily text-based,» although it allows for binary data forms. Linux kernel creator Linus Torvalds, who is always clear about his feelings, said:
«I don’t actually have any particularly strong opinions on systemd itself. I’ve had issues with some of the core developers that I think are much too cavalier about bugs and compatibility, and I think some of the design details are insane (I dislike the binary logs, for example), but those are details, not big issues.» —Linus Torvalds, quoted in ZDNet’s «Linus Torvalds and others on Linux’s systemd» in 2014
The systemd journal files are stored in one or more subdirectories of /var/log/journal
. Log into a test system where you have root access, and make /var/log/journal
the present working directory (PWD). List the subdirectories there, choose one, and make it the PWD. You can look at these files in a number of ways. I started with the stat
command (note that the journal file names on your host will be different from mine):
[root@testvm1 3bccd1140fca488187f8a1439c832f07]# stat system@7ed846aadf1743139083681ec4042037-0000000000000001-0005a99c0280fd5f.journal
File: system@7ed846aadf1743139083681ec4042037-0000000000000001-0005a99c0280fd5f.journal
Size: 8388608 Blocks: 16392 IO Block: 4096 regular file
Device: fd04h/64772d Inode: 524384 Links: 1
Access: (0640/-rw-r-----) Uid: ( 0/ root) Gid: ( 190/systemd-journal)
Access: 2020-07-13 08:30:05.764291231 -0400
Modify: 2020-07-04 07:33:52.916001110 -0400
Change: 2020-07-04 07:33:52.916001110 -0400
Birth: -
[root@testvm1 3bccd1140fca488187f8a1439c832f07]#
The journal file is identified as a «regular» file, which is not especially helpful. The file
command identifies it as a «journal» file, but you already know that. Look inside the file with the dd
command. The following command sends the output data stream to STDOUT; you may want to pipe it through the less
pager:
[root@testvm1 3bccd1140fca488187f8a1439c832f07]# dd if=system@7ed846aadf1743139083681ec4042037-0000000000000001-0005a99c0280fd5f.journal | less
<SNIP>
9�P1�8��9_SOURCE_MONOTONIC_TIMESTAMP=191726���/��P����9MESSAGE=Inode-cache hash table entries: 1048576 (order: 11, 8388608 bytes, linear)�hx
9�P1�p�9��/��P�b������9��9_SOURCE_MONOTONIC_TIMESTAMP=191825�pdXY�7p�9��9MESSAGE=mem auto-init: stack:off, heap alloc:off, heap free:off�i��
��(n�O���@Y� �����Zս���82���7X�8�������8��DZR�����8<~B�4�<� �8tM˞8$����8��Ж��h9�&������9�����`@�9�pdXY�7b�ͺ��WV��9��9_SOURCE_MONOTONIC_TIM
ESTAMP=234745����4�h@�9��9MESSAGE=Memory: 12598028K/12963384K available (14339K kernel code, 2406K rwdata, 8164K rodata, 2468K init, 5072K b
ss, 365356K reserved, 0K cma-reserved)�j����(n�O���@Y� ����]��m�82���7X�8�������8��DZR�����8<~B�4�<� �8tM˞8$����8��Ж��h9�&�����9�ͺ��WV��9���
4�hbB���a��^��9��9_SOURCE_MONOTONIC_TIMESTAMP=234758��3�����9��9MESSAGE=random: get_random_u64 called from __kmem_cache_create+0x3e/0x610 wi
th crng_init=0�k���(n�O���@Y� ����j������82���7X��8C�X�Y"��8�������8��DZR�����8<~B�4�<� �8tM˞8$����8��Ж�à�9B���a���9�3���b�8�ȭ�����9h�9_SO�9h�9MESSAGE=SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1�l����(n�O���@Y� ������z��X�82���7X�8�������8��DZR�����8<~B�4�<� �8tM˞
b�(+I)�x�9�9_SOURCE_MONOTONIC_TIMESTAMP=235444r�%/p��9�9MESSAGE=Kernel/User page tables isolation: enabled�m����(n�O���@Y� ����k��B0��8
2���7X�8�������8��DZR�����8<~B�4�<� �8tM˞8$����8��Ж��h9�&����8�9�(+I)Ҡ�9�%/pb8O{ W���8�9��9_SOURCE_MONOTONIC_TIMESTAMP=235464u�N`�FP M��9
��9MESSAGE=ftrace: allocating 41361 entries in 162 pages�n����(n�O���@Y�
<SNIP>
Even this small portion of the data stream from the dd
command shows an interesting mixture of ASCII text and binary data. Another useful tool is the strings
command, which simply displays all the ASCII text strings contained in a file and ignores the binary data:
[root@testvm1 3bccd1140fca488187f8a1439c832f07]# strings system@7ed846aadf1743139083681ec4042037-0000000000000001-0005a99c0280fd5f.journal
<SNIP>
MESSAGE=Linux version 5.7.6-201.fc32.x86_64 (mockbuild@bkernel01.iad2.fedoraproject.org) (gcc version 10.1.1 20200507 (Red Hat 10.1.1-1) (GC
C), GNU ld version 2.34-3.fc32) #1 SMP Mon Jun 29 15:15:52 UTC 2020
MESSAGE
_BOOT_ID=6e944f99ebd9405984090f829a927fa4
_BOOT_ID
_MACHINE_ID=3bccd1140fca488187f8a1439c832f07
_MACHINE_ID
_HOSTNAME=testvm1.both.org
_HOSTNAME
PRIORITY=6
MESSAGE=Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.7.6-201.fc32.x86_64 root=/dev/mapper/VG01-root ro resume=/dev/mapper/VG01-swap rd.lv
m.lv=VG01/root rd.lvm.lv=VG01/swap rd.lvm.lv=VG01/usr selinux=0
MESSAGE=x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
MESSAGE=x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
MESSAGE=x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
Z_g3;
MESSAGE=x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
Z_g3;
MESSAGE=x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format.
MESSAGE=BIOS-provided physical RAM map:
`k2X
MESSAGE=BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
MESSAGE=BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
MESSAGE=BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
PyLM
MESSAGE=BIOS-e820: [mem 0x0000000000100000-0x00000000dffeffff] usable
MESSAGE=BIOS-e820: [mem 0x00000000dfff0000-0x00000000dfffffff] ACPI data
MESSAGE=BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
MESSAGE=BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
MESSAGE=BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
MESSAGE=BIOS-e820: [mem 0x0000000100000000-0x00000003373fffff] usable
<SNIP>
This data can be interpreted by humans, and this particular segment looks very similar to the output data stream from the dmesg
command. I’ll leave you to explore further on your own, but my conclusion is that the journal files are clearly a mixture of binary and ASCII text. That mix makes it cumbersome to use traditional text-based Linux tools to extract usable data. But there is a better way that provides many possibilities for extracting and viewing journal data.
About journalctl
The journalctl
command is designed to extract usable information from the systemd journals using powerful and flexible criteria for identifying the desired data. Previous articles in this series have described journalctl
, and there is more to know.
I’ll review a bit first and start with some basics in case you have not read the previous articles or just need a refresher.
You can use the journalctl
command without any options or arguments to view the systemd journal that contains all journal and log information:
[root@testvm1 ~]# journalctl
-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Thu 2020-07-16 10:30:43 EDT. --
Jun 08 07:47:20 testvm1.both.org kernel: Linux version 5.6.6-300.fc32.x86_64 (mockbuild@bkernel03.phx2.fedoraproject.org) (gcc version 10.0>
Jun 08 07:47:20 testvm1.both.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.6.6-300.fc32.x86_64 root=/dev/mapper/VG01-root ro >
Jun 08 07:47:20 testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
Jun 08 07:47:20 testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
Jun 08 07:47:20 testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
Jun 08 07:47:20 testvm1.both.org kernel: x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
Jun 08 07:47:20 testvm1.both.org kernel: x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format.
Jun 08 07:47:20 testvm1.both.org kernel: BIOS-provided physical RAM map:
Jun 08 07:47:20 testvm1.both.org kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
<SNIP>
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1765] dhcp4 (enp0s3): option requested_routers => '1'
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1765] dhcp4 (enp0s3): option requested_static_routes => '1'
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1765] dhcp4 (enp0s3): option requested_subnet_mask => '1'
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1765] dhcp4 (enp0s3): option requested_time_offset => '1'
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1766] dhcp4 (enp0s3): option requested_wpad => '1'
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1766] dhcp4 (enp0s3): option routers => '192.168.0.2>
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1766] dhcp4 (enp0s3): option subnet_mask => '255.255.255>
Jul 16 09:51:00 testvm1.both.org NetworkManager[760]: <info> [1594907460.1766] dhcp4 (enp0s3): state changed extended -> extended
Jul 16 09:51:00 testvm1.both.org systemd[1]: Starting Network Manager Script Dispatcher Service...
Jul 16 09:51:00 testvm1.both.org systemd[1]: Started Network Manager Script Dispatcher Service.
Jul 16 09:51:00 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-dispatcher com>
Jul 16 09:51:10 testvm1.both.org systemd[1]: NetworkManager-dispatcher.service: Succeeded.
Jul 16 09:51:10 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-dispatcher comm>
Jul 16 09:59:13 testvm1.both.org systemd[1]: Starting dnf makecache...
Jul 16 09:59:13 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=dnf-makecache comm="systemd" >
Jul 16 09:59:13 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=dnf-makecache comm="systemd" e>
Jul 16 09:59:13 testvm1.both.org systemd[1]: dnf-makecache.service: Succeeded.
Jul 16 09:59:13 testvm1.both.org systemd[1]: Finished dnf makecache.
Jul 16 09:59:14 testvm1.both.org dnf[378549]: Metadata cache refreshed recently.
Jul 16 10:00:42 testvm1.both.org systemd[1]: Starting system activity accounting tool...
Jul 16 10:00:42 testvm1.both.org systemd[1]: sysstat-collect.service: Succeeded.
Jul 16 10:00:42 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=sysstat-collect comm="systemd>
Jul 16 10:00:42 testvm1.both.org systemd[1]: Finished system activity accounting tool.
Jul 16 10:00:42 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=sysstat-collect comm="systemd">
Jul 16 10:01:01 testvm1.both.org CROND[378562]: (root) CMD (run-parts /etc/cron.hourly)
Jul 16 10:01:01 testvm1.both.org run-parts[378565]: (/etc/cron.hourly) starting 0anacron
Jul 16 10:01:01 testvm1.both.org run-parts[378571]: (/etc/cron.hourly) finished 0anacron
You can also explicitly show the same data the dmesg
command presents. Open two terminal sessions next to each other and issue the dmesg
command in one and the following command in the other:
[root@testvm1 ~]# journalctl --dmesg
The only difference you should see is the time format. The dmesg
command is in a monotonic format that shows the number of seconds since the system boot. The journalctl
output is in a date and time format. The short-monotonic option displays the time since boot:
[root@testvm1 ~]# journalctl --dmesg -o short-monotonic
-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Mon 2020-07-20 13:01:01 EDT. --
[ 0.000000] testvm1.both.org kernel: Linux version 5.7.6-201.fc32.x86_64 (mockbuild@bkernel01.iad2.fedoraproject.org) (gcc version 10.1.>
[ 0.000000] testvm1.both.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.7.6-201.fc32.x86_64 root=/dev/mapper/VG01-root ro r>
[ 0.000000] testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
[ 0.000000] testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
[ 0.000000] testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
[ 0.000000] testvm1.both.org kernel: x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
[ 0.000000] testvm1.both.org kernel: x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format.
<snip>
[ 0.000002] testvm1.both.org kernel: clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 8815905914>
[ 0.000005] testvm1.both.org kernel: tsc: Detected 2807.988 MHz processor
[ 0.001157] testvm1.both.org kernel: e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
[ 0.001159] testvm1.both.org kernel: e820: remove [mem 0x000a0000-0x000fffff] usable
[ 0.001162] testvm1.both.org kernel: last_pfn = 0x24ec00 max_arch_pfn = 0x400000000
[ 0.001172] testvm1.both.org kernel: MTRR default type: uncachable
[ 0.001173] testvm1.both.org kernel: MTRR variable ranges disabled:
[ 0.001173] testvm1.both.org kernel: Disabled
[ 0.001174] testvm1.both.org kernel: x86/PAT: MTRRs disabled, skipping PAT initialization too.
[ 0.001176] testvm1.both.org kernel: CPU MTRRs all blank - virtualized system.
[ 0.001179] testvm1.both.org kernel: x86/PAT: Configuration [0-7]: WB WT UC- UC WB WT UC- UC
[ 0.001182] testvm1.both.org kernel: last_pfn = 0xdfff0 max_arch_pfn = 0x400000000
[ 0.001238] testvm1.both.org kernel: found SMP MP-table at [mem 0x0009fff0-0x0009ffff]
[ 0.081068] testvm1.both.org kernel: RAMDISK: [mem 0x34194000-0x360c1fff]
[ 0.081088] testvm1.both.org kernel: ACPI: Early table checksum verification disabled
<snip>
[ 34.037575] testvm1.both.org kernel: 16:43:32.734466 main 6.1.10_Fedora r138449 started. Verbose level = 0
[ 34.042209] testvm1.both.org kernel: 16:43:32.739032 main vbglR3GuestCtrlDetectPeekGetCancelSupport: Supported (#1)
[ 55.746944] testvm1.both.org kernel: e1000: enp0s3 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
[ 55.747738] testvm1.both.org kernel: IPv6: ADDRCONF(NETDEV_CHANGE): enp0s3: link becomes ready
<snip>
lines 624-681/681 (END)
The journalctl
command has many options, including the -o
(output) option with several suboptions that allow you to select a time and date format that meets different sets of requirements. I have listed most of them below, along with a short description that I expanded or modified from the journalctl
man page. Note that the primary difference between most of these is the format of the date and time, and the other information remains the same.
journalctl time and date formats
- short: This is the default format and generates an output that is most closely like the formatting of classic syslog files, showing one line per journal entry. This option shows journal metadata including the monotonic time since boot, the fully qualified hostname, and the unit name such as the kernel, DHCP, etc.
Jul 20 08:43:01 testvm1.both.org kernel: Inode-cache hash table entries: 1048576 (order: 11, 8388608 bytes, linear)
- short-full: This format is very similar to the default but shows timestamps in the format the
--since=
and--until=
options accept. Unlike the timestamp information shown in short output mode, this mode includes weekday, year, and timezone information in the output and is locale-independent.Mon 2020-06-08 07:47:20 EDT testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
- short-iso: The short-iso format is very similar to the default, but shows ISO 8601 wallclock timestamps.
2020-06-08T07:47:20-0400 testvm1.both.org kernel: kvm-clock: Using msrs 4b564d01 and 4b564d00
- short-iso-precise:
2020-06-08T07:47:20.223738-0400 testvm1.both.org kernel: Booting paravirtualized kernel on KVM
- short-monotonic:
[ 2.091107] testvm1.both.org kernel: ata1.00: ATA-6: VBOX HARDDISK, 1.0, max UDMA/133
- short-precise: This format is also similar to the default but shows classic syslog timestamps with full microsecond precision.
Jun 08 07:47:20.223052 testvm1.both.org kernel: BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
- short-unix: Like the default, but shows seconds passed since January 1, 1970, UTC instead of wallclock timestamps («Unix time»). The time is shown with microsecond accuracy.
1591616840.232165 testvm1.both.org kernel: tcp_listen_portaddr_hash hash table entries: 8192
- cat: Generates a very terse output only showing the message of each journal entry with no metadata, not even a timestamp.
ohci-pci 0000:00:06.0: irq 22, io mem 0xf0804000
- verbose: This format shows the full data structure for all the entry items with all fields. This is the format option that is most different from all the others.
Mon 2020-06-08 07:47:20.222969 EDT [s=d52ddc9f3e8f434b9b9411be2ea50b1e;i=1;b=dcb6dcc0658e4a8d8c781c21a2c6360d;m=242d7f;t=5a7912c6148f9;x=8f> _SOURCE_MONOTONIC_TIMESTAMP=0 _TRANSPORT=kernel PRIORITY=5 SYSLOG_FACILITY=0 SYSLOG_IDENTIFIER=kernel MESSAGE=Linux version 5.6.6-300.fc32.x86_64 (mockbuild@bkernel03.phx2.fedoraproject.org) (gcc version 10.0.1 20200328 (Red Hat 10.0.1-0> _BOOT_ID=dcb6dcc0658e4a8d8c781c21a2c6360d _MACHINE_ID=3bccd1140fca488187f8a1439c832f07 _HOSTNAME=testvm1.both.org
Other choices, available with the -o
option, allow exporting the data in various formats such as binary or JSON. I also find the -x
option illuminating because it can show additional explanatory messages for some journal entries. If you try this option, be aware that it can greatly increase the output data stream. For example, the additional information for an entry like:
[ 4.503737] testvm1.both.org systemd[1]: Starting File System Check on /dev/mapper/VG01-root...
[ 4.691555] testvm1.both.org systemd-fsck[548]: root: clean, 1813/327680 files, 48555/1310720 blocks
[ 4.933065] testvm1.both.org systemd[1]: Finished File System Check on /dev/mapper/VG01-root.
expands to this:
[ 4.503737] testvm1.both.org systemd[1]: Starting File System Check on /dev/mapper/VG01-root...
-- Subject: A start job for unit systemd-fsck-root.service has begun execution
-- Defined-By: systemd
-- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- A start job for unit systemd-fsck-root.service has begun execution.
--
-- The job identifier is 36.
[ 4.691555] testvm1.both.org systemd-fsck[548]: root: clean, 1813/327680 files, 48555/1310720 blocks
[ 4.933065] testvm1.both.org systemd[1]: Finished File System Check on /dev/mapper/VG01-root.
-- Subject: A start job for unit systemd-fsck-root.service has finished successfully
-- Defined-By: systemd
-- Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- A start job for unit systemd-fsck-root.service has finished successfully.
--
-- The job identifier is 36
There is some new information here, but I think the main benefit is that the information is contextualized to clarify the original terse messages to some degree.
Narrowing the search
Most of the time, it is not necessary or even desirable to list all the journal entries and manually search through them. Sometimes I look for entries related to a specific service, and other times I look for entries that happened at specific times. The journalctl
command provides powerful options that allow you to see only the data you are interested in finding.
Start with the --list-boots
option, which lists all the boots during the time period when journal entries exist. Note that the journalctl.conf
file may specify that journal entries are discarded after they reach a certain age or after the storage device (HDD/SSD) space taken by the journals reaches a specified maximum amount:
[root@testvm1 ~]# journalctl --list-boots
-10 dcb6dcc0658e4a8d8c781c21a2c6360d Mon 2020-06-08 07:47:20 EDT—Mon 2020-06-08 07:53:05 EDT
-9 7d61951a85f445c5946774aaae8bc2a4 Fri 2020-07-03 15:50:06 EDT—Fri 2020-07-03 18:21:23 EDT
-8 1b3a847577e544b4a2679fe576b62206 Fri 2020-07-03 18:21:58 EDT—Fri 2020-07-03 22:10:54 EDT
-7 5fef01a3568743af99118107ca6f61ae Fri 2020-07-03 22:18:41 EDT—Sat 2020-07-04 06:50:19 EDT
-6 6e944f99ebd9405984090f829a927fa4 Sat 2020-07-04 07:33:25 EDT—Sat 2020-07-04 07:58:59 EDT
-5 ec8b0c81ca4744b1bad071bdef432959 Sat 2020-07-04 08:12:06 EDT—Sat 2020-07-04 09:12:47 EDT
-4 cb173ec716824e21b87ccf6cb43a9a99 Sat 2020-07-04 10:19:53 EDT—Sat 2020-07-04 11:31:03 EDT
-3 4fe354a893194409843aa9623a36dbb0 Sat 2020-07-04 07:59:58 EDT—Sun 2020-07-05 09:39:30 EDT
-2 06fb81f1b29e4f68af9860844668446c Mon 2020-07-06 06:27:05 EDT—Mon 2020-07-13 08:50:06 EDT
-1 33dbf8e6b9de4113a591c4f487d0ac37 Mon 2020-07-13 04:50:33 EDT—Thu 2020-07-16 13:49:32 EDT
0 75c9b70913934748b5396b3b172bee50 Mon 2020-07-20 08:43:01 EDT—Fri 2020-07-24 12:44:06 EDT
The most recent boot ID appears at the bottom; it is the long, random hex number. You can use this data to view the journals for a specific boot. This can be specified using the boot offset number in the left-most column or the UUID in the second column. This command displays the journal for the boot instance with the offset of -2
—the second previous boot from the current one:
[root@testvm1 ~]# journalctl -b -2
-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Fri 2020-07-24 12:44:06 EDT. --
Jul 06 06:27:05 testvm1.both.org kernel: Linux version 5.7.6-201.fc32.x86_64 (mockbuild@bkernel01.iad2.fedoraproject.org) (gcc version 10.1>
Jul 06 06:27:05 testvm1.both.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.7.6-201.fc32.x86_64 root=/dev/mapper/VG01-root ro >
Jul 06 06:27:05 testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
Jul 06 06:27:05 testvm1.both.org kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
<SNIP>
Or you could use the UUID for the desired boot. The offset numbers change after each boot, but the UUID does not:
[root@testvm1 ~]# journalctl -b 06fb81f1b29e4f68af9860844668446c
The -u
option allows you to select specific units to examine. You can use a unit name or a pattern for matching, and you can use this option multiple times to match multiple units or patterns. In this example, I used it in combination with -b
to show chronyd journal entries for the current boot:
[root@testvm1 ~]# journalctl -u chronyd -b
-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Sun 2020-07-26 09:10:47 EDT. --
Jul 20 12:43:31 testvm1.both.org systemd[1]: Starting NTP client/server...
Jul 20 12:43:31 testvm1.both.org chronyd[811]: chronyd version 3.5 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCD>
Jul 20 12:43:31 testvm1.both.org chronyd[811]: Frequency -0.021 +/- 0.560 ppm read from /var/lib/chrony/drift
Jul 20 12:43:31 testvm1.both.org chronyd[811]: Using right/UTC timezone to obtain leap second data
Jul 20 12:43:31 testvm1.both.org systemd[1]: Started NTP client/server.
Jul 20 12:44:00 testvm1.both.org chronyd[811]: Selected source 192.168.0.52
Jul 20 12:44:00 testvm1.both.org chronyd[811]: System clock TAI offset set to 37 seconds
Jul 20 12:44:00 testvm1.both.org chronyd[811]: System clock wrong by 1.412227 seconds, adjustment started
Jul 20 12:44:01 testvm1.both.org chronyd[811]: System clock was stepped by 1.412227 seconds
[root@testvm1 ~]#
Suppose you want to look at events that were recorded between two arbitrary times. You can also use -S
(--since
) and -U
(--until
) to specify the beginning and ending times. The following command displays journal entries starting at 15:36:00 on July 24, 2020, through the current time:
[root@testvm1 ~]# journalctl -S "2020-07-24 15:36:00"
And this command displays all journal entries starting at 15:36:00 on July 24, 2020, until 16:00:00 on July 25:
[root@testvm1 ~]# journalctl -S "2020-07-24 15:36:00" -U "2020-07-25 16:00:00"
This command combines -S
, -U
, and -u
to give journal entries for the NetworkManager service unit starting at 15:36:00 on July 24, 2020, until 16:00:00 on July 25:
[root@testvm1 ~]# journalctl -S "2020-07-24 15:36:00" -U "2020-07-25 16:00:00" -u NetworkManager
Some syslog facilities, such as cron, auth, mail, daemon, user, and more, can be viewed with the --facility
option. You can use --facility=help
to list the available facilities. In this example, the mail facility is not the Sendmail service that would be used for an email service, but the local client used by Linux to send email to root as event notifications. Sendmail actually has two parts, the server, which (for Fedora and related distributions) is not installed by default, and the client, which is always installed so that it can be used to deliver system emails to local recipients, especially root:
[root@testvm1 ~]# journalctl --facility=mail
The journalctl
man page lists all the options that can be used to narrow searches. The table below summarizes some of the options I use most frequently. Most of these options can be used in various combinations to further narrow a search. Refer to my previous article Analyzing systemd calendar and timespans for details on creating and testing timestamps, as well as important tips like using quotes around timestamps.
Options to narrow searches of the journal
Option | Description |
---|---|
--list-boots |
This displays a list of boots. The information can be used to show journal entries only for a particular boot. |
-b [offset|boot ID] |
This specifies which boot to display information for. It includes all journal entries from that boot through shutdown or reboot. |
--facility=[facility name] |
This specifies the facility names as they’re known to syslog. Use --facility=help to list the valid facility names. |
-k , --dmesg |
These display only kernel messages and are equivalent to using the dmesg command. |
-S , --since [timestamp] |
These show all journal entries since (after) the specified time. They can be used with --until to display an arbitrary range of time. Fuzzy times such as «yesterday» and «2 hours ago»—with quotes—are also allowed. |
-u [unit name] |
The -u option allows you to select specific units to examine. You can use a unit name or a pattern for matching. This option can be used multiple times to match multiple units or patterns. |
-U , --until [timestamp] |
These show all journal entries until (prior to) the specified time. They can be used with --since to display an arbitrary range of time. Fuzzy times such as «yesterday» and «2 hours ago»—with quotes—are also allowed. |
Other interesting options
The journalctl
program offers some other interesting options, as well. These are useful for refining the data search, specifying how the journal data is displayed, and managing the journal files.
Additional interesting journalctl options
Option | Description |
-f , --follow |
This journalctl option is similar to using the tail -f command. It shows the most recent entries in the journal that match whatever other options have been specified and also displays new entries as they occur. This can be useful when watching for events and when testing changes. |
-e , --pager-end |
The -e option displays the end of the data stream instead of the beginning. This does not reverse the order of the data stream, rather it causes the pager to jump to the end. |
--file [journal filename] |
This names a specific journal file in /var/log/journal/<journal subdirectory> . |
-r , --reverse |
This option reverses the order of the journal entries in the pager so that the newest are at the top rather than the bottom. |
-n , --lines=[X] |
This shows the most recent X number of lines from the journal. |
--utc |
This displays times in UTC rather than local time. |
-g , --grep=[REGEX] |
I like the -g option because it enables me to search for specific patterns in the journal data stream. This is just like piping a text data stream through the grep command. This option uses Perl-compatible regular expressions. |
--disk-usage |
This option displays the amount of disk storage used by the current and archived journals. It might not be as much as you think. |
--flush |
Journal data stored in the virtual filesystem /run/log/journal/ , which is volatile storage, is written to /var/log/journal/ which is persistent storage. This option ensures that all data is flushed to /run/log/journal/ at the time it returns. |
--sync |
This writes all unwritten journal entries (still in RAM but not in /run/log/journal ) to the persistent filesystem. All journal entries known to the journaling system at the time the command is entered are moved to persistent storage. |
--vacuum-size= --vacuum-time= --vacuum-files= |
These can be used singly or in combination to remove the oldest archived journal files until the specified condition is met. These options only consider archived files, and not active files, so the result might not be exactly what was specified. |
I’ll explore some of these entries below. More options can be found in the journalctl
man page.
Journal files
If you have not already, be sure to list the files in the journal directory on your host. Remember that the name of the directory containing the journal files is a long, random number. This directory contains multiple active and archived journal files, including some for users:
[root@david ~]# cd /var/log/journal/ad8f29ed15044f8ba0458c846300c2a4/
[root@david ad8f29ed15044f8ba0458c846300c2a4]# ll
total 352308
-rw-r-----+ 1 root systemd-journal 33554432 May 28 13:07 system@0c91aaef57c441859ea5e421edff6528-0000000000000001-0005a6703120d448.journal
-rw-r-----+ 1 root systemd-journal 109051904 Jun 23 21:24 system@0c91aaef57c441859ea5e421edff6528-0000000000008238-0005a6b85e4e03c6.journal
-rw-r-----+ 1 root systemd-journal 100663296 Jul 21 18:39 system@0c91aaef57c441859ea5e421edff6528-0000000000021f3e-0005a8ca55efa66a.journal
-rw-r-----+ 1 root systemd-journal 41943040 Jul 30 09:34 system.journal
-rw-r-----+ 1 root systemd-journal 8388608 May 28 13:07 user-1000@037bcc7935234a5ea243b3af304fd08a-0000000000000c45-0005a6705ac48a3c.journal
-rw-r-----+ 1 root systemd-journal 16777216 Jun 23 21:24 user-1000@bc90cea5294447fba2c867dfe40530db-0000000000008266-0005a6b85e910761.journal
-rw-r-----+ 1 root systemd-journal 41943040 Jul 21 16:08 user-1000@bc90cea5294447fba2c867dfe40530db-0000000000021f4b-0005a8ca68c83ab7.journal
-rw-r-----+ 1 root systemd-journal 8388608 Jul 30 09:34 user-1000.journal
[root@david ad8f29ed15044f8ba0458c846300c2a4]#
You can see the user files in this listing for the user ID (UID) 1000, which is my Linux account. The --files
option allows me to see the content of specified files, including the user files:
[root@david ad8f29ed15044f8ba0458c846300c2a4]# journalctl --file user-1000.journal
<SNIP>
Jul 29 14:13:32 david.both.org tumblerd[145509]: Registered thumbnailer /usr/bin/gdk-pixbuf-thumbnailer -s %s %u %o
Jul 29 14:13:32 david.both.org Thunar[2788]: ThunarThumbnailer: got 0 handle (Queue)
Jul 29 14:13:32 david.both.org Thunar[2788]: ThunarThumbnailer: got 0 handle (Error or Ready)
Jul 29 14:13:32 david.both.org Thunar[2788]: ThunarThumbnailer: got 0 handle (Finished)
Jul 29 14:15:33 david.both.org tumblerd[145552]: error: Broken zip file structure
Jul 29 14:20:34 david.both.org systemd[2466]: dbus-:1.2-org.freedesktop.thumbnails.Thumbnailer1@11.service: Succeeded.
Jul 29 14:34:17 david.both.org systemd[2466]: Starting Cleanup of User's Temporary Files and Directories...
Jul 29 14:34:17 david.both.org systemd[2466]: systemd-tmpfiles-clean.service: Succeeded.
Jul 29 14:34:17 david.both.org systemd[2466]: Finished Cleanup of User's Temporary Files and Directories.
Jul 29 14:48:26 david.both.org systemd[2466]: Started dbus-:1.2-org.freedesktop.thumbnails.Thumbnailer1@12.service.
Jul 29 14:48:26 david.both.org tumblerd[145875]: Registered thumbnailer gsf-office-thumbnailer -i %i -o %o -s %s
<SNIP>
This output shows, among other things, temporary file cleanup for the UID1000 user. Data relating to individual users may be helpful in locating the root cause of problems originating in user space. I found a number of interesting entries in this output. Try it on your host and see what you find.
Adding journal entries
It can be useful to add your own entries to the journal. This is accomplished with the systemd-cat
program that allows piping the STDOUT of a command or program to the journal. This command can be used as part of a pipeline on the command line or in a script:
[root@testvm1 ~]# echo "Hello world" | systemd-cat -p info -t myprog
[root@testvm1 ~]# journalctl -n 10
Jul 27 09:01:01 testvm1.both.org CROND[976442]: (root) CMD (run-parts /etc/cron.hourly)
Jul 27 09:01:01 testvm1.both.org run-parts[976445]: (/etc/cron.hourly) starting 0anacron
Jul 27 09:01:01 testvm1.both.org run-parts[976451]: (/etc/cron.hourly) finished 0anacron
Jul 27 09:07:53 testvm1.both.org unknown[976501]: Hello world
Jul 27 09:10:47 testvm1.both.org systemd[1]: Starting system activity accounting tool...
Jul 27 09:10:47 testvm1.both.org systemd[1]: sysstat-collect.service: Succeeded.
Jul 27 09:10:47 testvm1.both.org systemd[1]: Finished system activity accounting tool.
Jul 27 09:10:47 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=sysstat-collect comm="systemd" exe="/usr/lib/syst>
Jul 27 09:10:47 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=sysstat-collect comm="systemd" exe="/usr/lib/syste>
Jul 27 09:17:10 testvm1.both.org myprog[976516]: Hello world
[root@testvm1 ~]#
The -p
option specifies a priority, emerg, alert, crit, err, warning, notice, info, debug, or a value between 0 and 7 that represents each of those named levels. These priority values are the same as those defined by syslog(3)
. The default is info. The -t
option is an identifier, which can be any arbitrary short string, such as a program or script name. This string can be used for searches by the journalctl
command:
[root@testvm1 ~]# journalctl -t myprog
-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Mon 2020-07-27 09:21:57 EDT. --
Jul 27 09:17:10 testvm1.both.org myprog[976516]: Hello world
[root@testvm1 ~]#
Journal management
I use the --disk-usage
option to check on journal sizes, along with other commands relating to disk usage, to ensure that my /var
filesystem is not filling up:
[root@testvm1 ~]# journalctl --disk-usage
Archived and active journals take up 136.0M in the file system.
[root@testvm1 ~]#
The disk usage for the journals on the testvm1 host is about 136MB. The result on my primary workstation is 328MB, and the host I use for my firewall and router uses 2.8GB for the journals. Journal sizes depend greatly on the host’s use and daily run time. My physical hosts all run 24×7.
The /etc/systemd/journald.conf
file can be used to configure the journal file sizes, rotation, and retention times to meet any needs not met by the default settings. You can also configure the journal storage location—you can specify a directory on the storage device or whether to store everything in RAM, which is volatile storage. If the journals are stored in RAM, they will not be persistent between boots.
The default time unit in the journald.conf
file is seconds, but it can be overridden using the suffixes year
, month
, week
, day
, h
, or m
.
Suppose you want to limit the total amount of storage space allocated to journal files to 1GB, store all journal entries in persistent storage, keep a maximum of 10 files, and delete any journal archive files that are more than a month old. You can configure this in /etc/systemd/journald.conf
using:
SystemMaxUse=1G
Storage=persistent
SystemMaxFiles=10
MaxRetentionSec=1month
By default, the SystemMaxUse
is 10% of available disk space. The default settings have been fine for the systems I work with, and I have not needed to change any of them. The journald.conf
man page states that the time-based settings for specifying how long to store journal entries in a single file or to retain older files are normally not necessary. This is because file number and size configurations usually force rotation and deletion of old files before any time settings might be needed.
The SystemKeepFree
option ensures a specific amount of space is kept free for other data. Many databases and application programs use the /var
filesystem to store data, so ensuring enough available storage space may be critical in systems with smaller hard drives and minimum space allocated to /var
.
If you make changes to this configuration, be sure to monitor the results carefully for an appropriate period of time to ensure they are performing as expected.
Journal file rotation
The journal files are typically rotated automatically based upon the configuration in the /etc/systemd/journald.conf
file. Files are rotated whenever one of the specified conditions is met. So if, for example, the space allocated to journal files is exceeded, the oldest file(s) is deleted, the active file is made into an archive, and a new active file is created.
Journal files can also be rotated manually. I suggest using the --flush
option to ensure current data is moved to persistent storage before you run the command:
[root@testvm1 ~]# journalctl --rotate
There is another way to purge old journal files without performing a file rotation. The vacuum-size=
, vacuum-files=
, and vacuum-time=
commands can be used to delete old archive files down to a specified total size, number of files, or prior time. The option values consider only the archive files and not the active ones, so the resulting reduction in total file size might be somewhat less than expected.
The following command purges old archive files so that only ones that are less than one month old are left. You can use the s
, m
, h
, days
, months
, weeks
, and years
suffixes:
[root@testvm1 ~]# journalctl --vacuum-time=1month
This command deletes all archive files except for the four most recent ones. If there are fewer than four archive files, nothing will happen, and the original number of files remains:
[root@testvm1 ~]# journalctl --vacuum-files=4
This last vacuum
command deletes archive files until 200MB or less of archived files are left:
[root@testvm1 ~]# journalctl --vacuum-size=200M
Only complete files are deleted. The vacuum commands do not truncate archive files to meet the specification. They also work only on archive files, not active ones.
Final thoughts
This article looked at using the journalctl
command to extract various types of data from the systemd journal in different formats. It also explored managing journal files and how to add entries to the log from commands and scripts.
The systemd journal system provides a significant amount of metadata and context for entries compared to the old syslogd program. This additional data and the context available from the other journal entries around the time of an incident can help the sysadmin locate and resolve problems much faster than having to search multiple syslog files.
In my opinion, the journalctl
command meets the Unix philosophy that programs should do one thing and do it well. The only thing journalctl
does is extract data from the journal and provide many options for selecting and formatting that data. At about 85K, it is not very big. Of course, that does not include shared libraries, but those are, by definition, shared with other programs.
You should now have enough information to use the systemd journal more effectively. If you would like to know more than what I covered here, look in the man pages for journalctl
and systemd-cat
.
Resources
There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup. This list has grown since I started this series of articles to reflect the research I have done.
- DigitalOcean has a very good article about journalctl and how to view and manipulate systemd logs.
- The Fedora Project has a good, practical guide to systemd. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
- The Fedora Project also has a good cheat sheet that cross-references the old SystemV commands to comparable systemd ones.
- Red Hat documentation contains a good description of the Unit file structure as well as other important information.
- For detailed technical information about systemd and the reasons for creating it, check out Freedesktop.org’s description of systemd.
- Linux.com’s «More systemd fun» offers more advanced systemd information and tips.
There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
- Rethinking PID 1
- systemd for Administrators, Part I
- systemd for Administrators, Part II
- systemd for Administrators, Part III
- systemd for Administrators, Part IV
- systemd for Administrators, Part V
- systemd for Administrators, Part VI
- systemd for Administrators, Part VII
- systemd for Administrators, Part VIII
- systemd for Administrators, Part IX
- systemd for Administrators, Part X
- systemd for Administrators, Part XI