Логирование в systemd
Содержимое
Введение
Одним из значимых преимуществ systemd является его возможность работы с логами процессов и системы в целом. При использовании остальных инструментов, отличных от systemd, логи обычно сильно децентрализованы, разбросаны по разным демонам, что затрудняет управление ими. Система, собирающая логи, и управляющая ими называется журналом.
Журнал представлен демоном journald, который собирает сообщения ядра, сервисов, процессов и т.д. Мы же разберёмся, как работать с journalctl, позволяющим управлять записями, сохранёнными в журнале.
Логи, собранные в systemd, сохраняются централизованно — в двоичном формате, что сильно упрощает их обработку. Например, можно выбирать произвольные форматы вывода логов, в зависимости от текущих потребностей (например, JSON).
Журнал systemd может использоваться вместе с системной реализацией журнала, либо вообще заменить его.
Настройка системного времени
Одно из преимущество хранения данных журнала в бинарном виде — возможность просмотра лога в любой временной зоне, на лету, без преобразований. По умолчанию, показывается локальное время.
Для вывода списка временных зон введите команду:
1
|
$ timedatectl list-timezones
|
Для установки временной зоны, в свою очередь:
1
|
$ sudo timedatectl set-timezone zone
|
Для проверки правильности внесенных изменений — вывод статуса:
1
|
$ timedatectl status
|
Пример вывода:
1
|
Local time: Fri 2016-12-23 03:45:42 MSK<br> Universal time: Fri 2016-12-23 00:45:42 UTC<br> RTC time: Fri 2016-12-23 00:45:42<br> Time zone: Europe/Moscow (MSK, +0300)<br> Network time on: yes<br>NTP synchronized: yes<br> RTC in local TZ: no
|
Обычный просмотр логов
Вывод логов, собранных демоном journald выполняется с помощью journalctl. Для примера, запуск без параметров — последние события внизу:
1
|
$ journalctl
|
Вывод:
1
|
Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Stopped target Basic System.<br>Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Stopped target Sockets.<br>Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Stopped target Timers.<br>Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Stopped target Paths.<br>Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Reached target Shutdown.<br>Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Starting Exit the Session...<br>Dec 20 17:24:29 ubuntu-512mb systemd[20583]: Received SIGRTMIN+24 from PID 17216 (kill).<br>...
|
Как видите, время локальное. Для вывода UTC-времени — добавьте параметр —utc:
1
|
$ journalctl --utc
|
Если необходимы только события с момента текущей загрузки, добавьте параметр -b:
1
|
$ journalctl -b
|
Если нужны только сообщения ядра — воспользуйтесь параметром -k:
1
|
$ journalctl -k
|
Как Вы понимаете, если добавить -b, останутся только записи, относящиеся к последней загрузке системы:
1
|
$ journalctl -k -b
|
Для вывода списка прошедших загрузок системы — выполните:
1
|
$ journalctl --list-boots
|
Текущая загрузка под номер 0. Предыдущие имеют отрицательные номера: -1, -2, …
1
|
-2 6cc1de0fb9a8421094b47fab2a9d0296 Wed 2016-11-23 12:36:44 MSK—Thu 2016-12-01 13:42:09 MSK<br>-1 28ed3b9d1fa44799927e41dedc875764 Thu 2016-12-01 13:43:30 MSK—Sun 2016-12-11 12:15:35 MSK<br> 0 2ed1975fc7a742afad1e89839c0410c6 Sun 2016-12-11 12:16:11 MSK—Fri 2016-12-23 03:44:04 MSK
|
Можно вывести информацию о предпоследней загрузке следующим образом:
1
|
$ journalctl -b -1
|
Или же сославшись на конкретный ID загрузки:
1
|
$ journalctl -b 28ed3b9d1fa44799927e41dedc875764
|
Временные окна
Несмотря на то, что просматривать логи, распределенные по загрузкам системы — довольно удобно, бывают случаи, когда необходимо вывести события, заключенные в каких-либо других временных рамках.
Для этого предназначены опции —since и —until.
Формат даты-времени — следующий:
ГГГГ-ММ-ДД ЧЧ:ММ:СС
К примеру, вывод всех события, начиная с 3-х часов ночи 1 декабря 2016 года:
1
|
$ journalctl --since "2016-12-01 03:00:00"
|
Или показ событий между 1 и 8 декабря:
1
|
$ journalctl --since "2016-12-01 03:00:00" --until "2016-12-08 00:03:00"
|
Также, имеется поддержка ключевых слов «yesterday», «today», «now» (вчера, сегодня, сейчас).
К примеру, вчерашние события:
1
|
journalctl --since yesterday
|
Фильтрация записей
Выше мы узнали, как задать временные рамки для просмотра логов. Но есть и другие способы фильтрации.
По юниту
Собственно, самый часто используемая возможность — фильтрация по имени юнита:
1
|
$ journalctl -u nginx.service
|
Как и всегда, можно добавлять параметры — к примеру, временные рамки. Например, вывод только сегодняшних событий с указанным юнитом:
1
|
$ journalctl -u nginx.service --since today
|
Помните, что в параметрах можно указать более одного юнита:
1
|
$ journalctl -u nginx.service -u php-fpm.service --since today
|
По процессу, пользователю, ID группы
К примеру, если нужны события только, относящиеся к процессу с заданным PID:
1
|
$ journalctl _PID=8125
|
Также можно узнать ID группы пользователей:
1
2
|
$ id -u www-data
33
|
И также использовать его как параметр:
1
|
$ journalctl _UID=33 --since today
|
Полный список полей, по которым доступна фильтрация:
1
|
$ man systemd.journal-fields
|
По пути запуска
Допустим, нужны события, связанные с bash. Выполним:
1
|
$ journalctl /usr/bin/bash
|
По приоритету
Очень важна возможность фильтрации сообщений по их приоритету:
Допустим, так можно вывести только те записи, которые помечены как ошибки:
1
|
$ journalctl -p err -b
|
Приведём полный список приоритетов (добавьте цифру после параметра p):
0: авария
1: предупреждение
2: критический
3: ошибка
4: предупреждение
5: уведомление
6: информация
7: отладка
Изменение отображения журнала
Выше мы рассмотрели фильтрацию по различным критериям, сейчас же — перейдём к способам видоизменения журнала.
Ограничение или расширения вывода
По умолчанию, journalctl не переносит строки по ширине экрана. Чтобы сократить вывод по ширине экрана — выполните:
1
|
$ journalctl --no-full
|
Чтобы выводить даже непечатные символы:
1
|
$ journalctl -a
|
Если вы обрабатываете вывод утилиты какими-то программными инструментами, Вам может понадобиться вывод в standard out — тогда не будет разделения на страницы:
1
|
$ journalctl --no-pager
|
Форматы вывода
Посредством параметра -o нам доступен ряд форматов вывода.
Конечно же, JSON:
1
|
$ journalctl -b -u nginx -o json
|
Пример вывода:
1
|
<pre class="inline:true decode:1 " >{ "__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" }
|
Это очень удобный формата для программного парсинга внешними утилитами. Можно отформатировать вывод:
1
|
$ journalctl -b -u nginx -o json-pretty
|
Вывод куда более удобен для чтения:
1
|
<pre class="inline:true decode:1 " >{<br> "__CURSOR" : "s=13a21661cf4948289c63075db6c25c00;i=116f1;b=81b58db8fd9046ab9f847ddb82a2fa2d;m=19f0daa;t=50e33c33587ae;x=e307daadb4858635",<br> "__REALTIME_TIMESTAMP" : "1422990364739502",<br> "__MONOTONIC_TIMESTAMP" : "27200938",<br> "_BOOT_ID" : "81b58db8fd9046ab9f847ddb82a2fa2d",<br> "PRIORITY" : "6",<br> "_UID" : "0",<br> "_GID" : "0",<br> "_CAP_EFFECTIVE" : "3fffffffff",<br> "_MACHINE_ID" : "752737531a9d1a9c1e3cb52a4ab967ee",<br> "_HOSTNAME" : "desktop",<br> "SYSLOG_FACILITY" : "3",<br> "CODE_FILE" : "src/core/unit.c",<br> "CODE_LINE" : "1402",<br> "CODE_FUNCTION" : "unit_status_log_starting_stopping_reloading",<br> "SYSLOG_IDENTIFIER" : "systemd",<br> "MESSAGE_ID" : "7d4958e842da4a758f6c1cdc7b36dcc5",<br> "_TRANSPORT" : "journal",<br> "_PID" : "1",<br> "_COMM" : "systemd",<br> "_EXE" : "/usr/lib/systemd/systemd",<br> "_CMDLINE" : "/usr/lib/systemd/systemd",<br> "_SYSTEMD_CGROUP" : "/",<br> "UNIT" : "nginx.service",<br> "MESSAGE" : "Starting A high performance web server and a reverse proxy server...",<br> "_SOURCE_REALTIME_TIMESTAMP" : "1422990364737973"<br>}
|
Приведём полный список форматов вывода:
cat: отображает только поле сообщения
export: бинарный формат вывода
json: стандартный JSON, одна запись на строку
json-pretty: отформатированный, человеко-читаемый JSON
short: стиль вывода syslog по умолчанию
short-iso: формат по-умолчанию, стандарт ISO 8601
short-monotonic: монотонные временные метки
short-precise: с добавлением микросекунд
verbose: принудительный вывод даже скрытых записей
Мониторинг текущих событий
Аналогично утилите tail, только соответствующая функциональность уже встроена в journalctl.
Вывод последних 25 записей:
1
|
$ journalctl -n 25
|
Отслеживание журнала
Для обновления вывода на экрана по мере поступления записей в лог — выполните:
1
|
$ journalctl -f
|
Управление журналом
Мы разобрали многое, теперь осталось затронуть некоторые вопросы администрирования журнала.
Вычисление занятого дискового пространства
Для вывода занятого журналом дискового пространства:
1
|
$ journalctl --disk-usage
|
Удаление старых записей
Мы можем удалить самые старые записей, чтобы сократить размер журнала до заданного нами размера. Например:
1
|
$ sudo journalctl --vacuum-size=1G
|
Или к примеру, можно удалить записи старше года:
1
|
$ sudo journalctl --vacuum-time=1years
|
Заключение
В данном руководстве мы рассмотрели основополагающие аспекты работы с утилитой journalctl.