Linux: Логи. Что это такое и справочник по базовым утилитам


Введение
Эта статья — справочник по утилитам, которые помогают читать логи и быстро находить в них причину проблем. Для одного сервера или домашней лаборатории (homelab) этого набора хватает в большинстве случаев.
journalctl— чтение журнала systemd, главный инструмент;dmesg— сообщения ядра;tail— конец файла и слежение за логом в реальном времени;less— постраничный просмотр больших логов;grep— поиск по шаблону;zgrep— поиск по сжатым, уже ротированным логам;last,lastb,lastlog— бинарные журналы входов в систему.
Для каждой утилиты вы найдёте, для чего она нужна, и таблицу со всеми ключами.
Примеры выполнены на Ubuntu. Команды, начинающиеся с sudo, требуют прав администратора. На своём сервере они вам понадобятся, на чужом сначала убедитесь, что вам можно.
Базовая информация
Что такое логи
Лог (log) — журнал событий: запись о том, что произошло, с временем и источником. Зачем они нужны? Ну, например, для того, чтобы посмотреть, почему N-й сервис не работает. Если вы обращаетесь, к примеру, за помощью в тематический чат с вопросом «у меня не работает nginx, помогите», вам в большинстве случаев скажут смотреть или прислать логи. Большая часть текстовых логов находится в каталоге /var/log:
Файл | Что внутри |
|---|---|
| Общий системный журнал: сообщения служб, ядра, планировщика |
| Входы в систему, |
| Сообщения ядра |
| Что и когда ставилось и удалялось |
| Бинарные журналы входов, читаются командами |
Часть файлов, возможно, вы не найдёте в своей системе, поскольку на разных дистрибутивах логи пишут сразу два механизма: journald и rsyslog.
journald — служба журналирования из состава systemd. Она перехватывает вывод всех служб и ядра, начиная с самой ранней стадии загрузки, и хранит его в бинарном индексированном виде. Читается командой journalctl.
rsyslog — демон (daemon, фоновая программа), который раскладывает сообщения по текстовым файлам в /var/log.
Так вот, на некоторых сборках или минимальных установках rsyslog может отсутствовать, тогда /var/log/syslog и /var/log/auth.log не существуют, а всё лежит только в journald.
Проверить можно командами systemctl is-active rsyslog (проверка, запущен ли rsyslog) и ls -lh /var/log/syslog /var/log/auth.log (проверка, есть ли текстовые файлы). Если у вас работают эти два механизма, то учитывайте, что сообщение обычно хранится дважды: в журнале и в текстовом файле. На Ubuntu journald пересылает копию в rsyslog: параметр ForwardToSyslog=yes включён в файле /usr/lib/systemd/journald.conf.d/syslog.conf, который поставляется вместе с systemd. В основном конфиге /etc/systemd/journald.conf этот параметр закомментирован (#ForwardToSyslog=no), так что искать yes там бесполезно.
Наверняка вы задались вопросом: а зачем нам эти два механизма? Если вкратце, journald мгновенно собирает логи в единую бинарную базу, а rsyslog забирает этот поток и раскладывает по привычным текстовым файлам в /var/log для совместимости со старым софтом, скриптами и системами мониторинга. Есть и второй плюс: если бинарный журнал повредится из-за сбоя, текстовые файлы читаются чем угодно, и часть логов удастся спасти.
Только не путайте это с резервной копией. Это не считается: оба хранилища лежат на одном диске, и при выходе диска из строя пропадут оба. От этого защищает, например, отправка логов на другой сервер.
Типы логов
Тип | Где искать | Когда смотреть |
|---|---|---|
Системные |
| Общая картина: что делали службы и ядро |
Безопасность и входы |
| Кто заходил, перебор паролей, |
Пакетные менеджеры |
| Что ставилось и обновлялось перед тем, как всё сломалось |
Службы и приложения |
| Работа конкретного сервиса |
Контейнеры |
| Вывод контейнеров лежит не в |
Установка и первый запуск |
| Почему свежий VPS настроился не так, как ожидалось |
Типы логов знать необязательно, но рекомендуется, если вы хотите запомнить, где что находится, или пишете своё ПО и хотите понимать, в чём разница между текстовыми (rsyslog) и бинарными (journald) логами. Текстовые читаются cat, less, grep. Бинарные так читать нельзя: нужны свои команды, например:
Бинарный лог | Чем читать |
|---|---|
Журнал journald |
|
|
|
|
|
|
|
Если сделать grep по btmp, вы получите сообщение типа binary file matches и подумаете, что искомого там нет. А оно там есть, grep просто отказался печатать бинарные данные.
Как устроена строка лога
В зависимости от того, где вы и что смотрите, структура логов может меняться, но базовые вещи всё же вы поймёте по этому примеру:
сен 17 18:10:13 veilos kernel: Linux version 7.0.0-31-generic (buildd@lcy02-amd>
сен 17 18:10:13— время события. Формат упрощён (в syslog дату и прочие параметры можно увидеть детальнее).veilos— имя компьютера (hostname).kernel:— источник сообщения (тут он указывает, что запись сделана ядром операционной системы).Linux version 7.0.0-31-generic— текст сообщения.(buildd@lcy02-amd>— обрезанный хвост строки (её обрезал пейджерless:journalctlзапускает его с обрезкой длинных строк, а символ>показывает, что текст не поместился в ширину терминала. Остальное видно, если прокрутить вправо, а с ключом--no-pagerстроки переносятся).
Не хватает уровней важности, о них ниже.
Уровни важности
У каждого сообщения есть уровень (приоритет). Их восемь, от самого серьёзного к самому незначительному:
Число | Имя | Значение |
|---|---|---|
0 |
| Система непригодна к работе |
1 |
| Действовать нужно немедленно |
2 |
| Критическая ошибка |
3 |
| Ошибка |
4 |
| Предупреждение (в |
5 |
| Обычное, но значимое событие |
6 |
| Информационное сообщение |
7 |
| Отладка |
Эти уровни нужны, например, в journalctl -p и dmesg -l, и ведут они себя по-разному:
journalctl -p errпоказывает уровеньerrи всё серьёзнее: 0, 1, 2 и 3;dmesg -l errпоказывает толькоerr, аcritи выше не покажет. Чтобы получить то же, что даётjournalctl, перечислите уровни:dmesg -l emerg,alert,crit,err.
Ротация логов
Текстовые логи растут, поэтому их периодически ротируют (rotate): текущий файл переименовывают, а вместо него создают новый пустой. Этим занимается logrotate. Он запускается по расписанию (таймером systemd или через cron), а настройки лежат в /etc/logrotate.conf и /etc/logrotate.d/.
Поэтому в /var/log рядом с syslog вы увидите такие файлы:
ls -lh /var/log/syslog*
-rw-r----- 1 syslog adm 6,6M окт 3 18:52 /var/log/syslog
-rw-r----- 1 syslog adm 13M сен 27 12:09 /var/log/syslog.1
-rw-r----- 1 syslog adm 1,8M сен 20 12:27 /var/log/syslog.2.gz
-rw-r----- 1 syslog adm 1,3M сен 13 08:36 /var/log/syslog.3.gz
-rw-r----- 1 syslog adm 987K сен 6 00:00 /var/log/syslog.4.gz
syslog.1 — предыдущий лог, он остаётся несжатым, потому что служба ещё может дописывать в него хвост. Начиная с .2 файлы сжаты gzip. Сколько копий хранится и как часто идёт ротация, зависит от конфигурации. На Ubuntu в /etc/logrotate.d/rsyslog стоят weekly и rotate 4: ротация раз в неделю, хранятся 4 копии. Именно поэтому даты в списке выше отстоят друг от друга на неделю.
Из этого следуют две вещи. Во-первых, grep по syslog не увидит событий недельной давности, для этого понадобится zgrep. Во-вторых, tail -f может «потерять» файл после ротации. Как с этим бороться, написано в разделе про tail.
Хранение журнала journald
Журнал journald может храниться в двух режимах:
постоянный: файлы лежат в
/var/log/journalи переживают перезагрузку;временный: файлы лежат в
/run/log/journal, то есть в памяти, и пропадают при перезагрузке. Режим выбирает параметрStorage=в/etc/systemd/journald.conf. По умолчанию стоитauto: журнал постоянный, если каталог/var/log/journalсуществует. На Ubuntu он есть сразу.
Для разбора «почему сервер упал и перезагрузился» это может быть критично, т.к. если журнал временный, логи предыдущей загрузки уже исчезли. Проверить режим можно так:
ls -d /var/log/journal
journalctl --list-boots
Права доступа
Многие логи читаются только от root или от групп adm и systemd-journal. Чтобы не писать sudo перед каждой командой, вы можете добавить себя в эти группы:
# Группа adm даёт чтение файлов в /var/log, systemd-journal даёт чтение журнала journald
sudo usermod -aG adm,systemd-journal $USER
Изменения применятся после нового входа в систему. Флаг
-aобязателен. Без него команда заменит все ваши дополнительные группы, и вы потеряете, например,sudo.
Учтите, что группа adm даёт чтение auth.log, а в нём видны имена пользователей, IP-адреса и попытки входа. Выдавайте её только тем, кому это действительно нужно. Исключение: файл /var/log/btmp принадлежит группе utmp, а не adm. Поэтому lastb потребует sudo, даже если вы состоите в adm.
Перед тем как выложить лог
Если вы собираетесь показать кусок лога на форуме, в issue или в чате, сначала проверьте его. В логах бывают токены в URL, пароли в параметрах запроса, имена пользователей, внутренние адреса и IP клиентов. Замените их заглушками до отправки. Это касается и вывода journalctl, и access.log, и логов приложений (да, в принципе, любого лога практически).
На этом базовое ознакомление с логами заканчивается, переходим к утилитам.
journalctl
journalctl читает журнал journald: вывод всех служб, сообщения ядра и сообщения ранней загрузки в одном месте. Его преимущество перед текстовыми файлами в том, что фильтровать можно по службе, времени, уровню и номеру загрузки, не прибегая к grep. Для разбора проблем это первая команда, с которой стоит начинать.
Общий вид: journalctl [ключи] [фильтры], где фильтры — это пары ПОЛЕ=значение, например _PID=1234 или _SYSTEMD_UNIT=cron.service.
Если у вас нет прав, команда напишет подсказку вида You are currently not seeing messages from other users and the system и покажет только ваш пользовательский журнал. Решение — группа systemd-journal из раздела про права доступа или sudo. Набор ключей зависит от версии systemd, свою версию покажет journalctl --version.
Флаг | Что делает |
|---|---|
| Показать системный журнал |
| Показать журнал текущего пользователя |
| Работать с локальным контейнером |
| Показать записи из всех доступных журналов |
| Взять файлы журнала из каталога |
| Прочитать конкретный файл журнала |
| Работать с другим корнем файловой системы |
| Работать с образом диска как с корнем файловой системы |
| Политика разбора образа диска |
| Показать данные из указанного пространства имён журнала |
| Записи не старше указанной даты. Формат: |
| Записи не новее указанной даты |
| Начать с записи, на которую указывает курсор |
| Показать записи после курсора |
| Показать записи после курсора из файла и обновить файл. Удобно для скриптов, которые читают журнал порциями |
| Текущая загрузка или указанная. |
| Логи указанной службы. Ключ можно повторять |
| Логи указанной пользовательской службы |
| Записи с указанным идентификатором syslog, обычно это имя программы |
| Фильтр по уровню. Одиночный уровень включает и всё серьёзнее. Диапазон задаётся так: |
| Записи указанных категорий: |
| Записи, в тексте сообщения которых есть совпадение с шаблоном (регулярное выражение). Если шаблон в нижнем регистре, регистр не учитывается |
| Принудительно включить или выключить учёт регистра в |
| Сообщения ядра за текущую загрузку, аналог |
| Формат вывода: |
| Какие поля печатать в режимах |
| Сколько записей показать |
| Новые записи сверху |
| Напечатать курсор после всех записей |
| Показывать время в UTC |
| Добавить пояснения к известным сообщениям, где они есть |
| Не выводить имя хоста |
| Обрезать длинные поля многоточием |
| Показать все поля целиком, включая длинные и непечатаемые |
| Следить за журналом в реальном времени, выход по |
| В режиме слежения показать все строки, а не только последние |
| Обрезать запись по первому символу перевода строки |
| Не выводить служебные сообщения и предупреждение о правах |
| Не использовать пейджер: в терминале вывод печатается сразу, без |
| Сразу перейти в конец в пейджере |
| Интервал смены ключа запечатывания FSS |
| Ключ для проверки запечатанного журнала FSS |
| Перезаписать существующую пару ключей FSS при |
| Показать справку |
| Показать версию |
| Перечислить все имена полей, которые встречаются в журнале |
| Перечислить все значения поля. |
| Краткий список загрузок, сохранённых в журнале |
| Сколько места занимают все файлы журнала |
| Удалить старые файлы, чтобы журнал занимал меньше указанного размера |
| Оставить только указанное число файлов журнала |
| Удалить файлы старше указанного срока |
| Проверить целостность файлов журнала |
| Сбросить несохранённые сообщения журнала на диск |
| Прекратить запись на диск, писать во временную файловую систему |
| То же, но ничего не делать, если каталог журнала лежит на корневом разделе |
| Перенести журнал из |
| Запросить немедленную ротацию файлов журнала |
| Показать заголовок журнала |
| Показать все идентификаторы сообщений каталога |
| Показать записи каталога сообщений |
| Обновить базу каталога сообщений |
| Сгенерировать новую пару ключей FSS |
dmesg
dmesg печатает кольцевой буфер ядра (kernel ring buffer). Туда ядро пишет всё про железо и драйверы: нашлись диски, поднялась сетевая карта, пошли ошибки ввода-вывода, сработал OOM killer. Буфер небольшой и фиксированного размера. Когда он заполняется, новые сообщения затирают старые, а после перезагрузки он пустой. Получается, что dmesg видит только текущую загрузку. Что было до неё, я смотрю через journalctl -k -b -1, но это работает только если журнал постоянный.
Файл /var/log/dmesg с командой не путайте. Это снимок буфера, который делается в конце загрузки, дальше он не обновляется. Также на Ubuntu и новых Debian от обычного пользователя dmesg может ругнуться: read kernel buffer failed: Operation not permitted. Дело в kernel.dmesg_restrict, значение смотрится командой sysctl kernel.dmesg_restrict. Там 1, значит, нужен sudo.
Без -T время в начале строки идёт в секундах с момента загрузки, вида [ 1234.567890]. Читать неудобно, зато оно точное. А вот -T иногда врёт, подробности в таблице.
Флаг | Что делает |
|---|---|
| Очистить буфер ядра |
| Прочитать все сообщения и очистить буфер |
| Отключить вывод сообщений на консоль |
| Включить вывод сообщений на консоль |
| Взять данные из файла вместо буфера ядра |
| Оставить только указанные категории (facility). Есть |
| Вывод для человека: пейджер, цвета, относительное время |
| Вывод в JSON |
| Показать сообщения ядра |
| Цвет: |
| Оставить только указанные уровни через запятую: |
| Задать уровень сообщений, которые идут на консоль |
| Не использовать пейджер |
| Метка времени в каждой строке многострочного сообщения |
| Сырой буфер |
| Не экранировать непечатаемые символы |
| Работать через |
| Размер буфера при запросе к кольцевому буферу ядра |
| Показать сообщения пользовательского уровня |
| Ждать новых сообщений |
| Ждать новых сообщений и печатать только их |
| Расшифровать категорию и уровень в названия |
| Показать разницу во времени между сообщениями |
| Локальное время и разница между сообщениями в читаемом виде |
| Время в виде даты. Может быть неточным: после suspend и hibernate оно сбивается |
| Не показывать время |
| Формат времени: |
| Показать строки с указанного времени |
| Показать строки до указанного времени |
| Показать справку |
| Показать версию |
tail
tail печатает конец файла. Для логов это самое подходящее поведение: проблема обычно в последних строках. А с ключом -f команда не завершается, а продолжает печатать строки по мере их появления, и вы видите, что происходит, прямо сейчас.
Если файлов несколько, перед каждым печатается заголовок с именем. Если файл не указан или указан -, команда читает стандартный ввод.
Различие для логов — между -f и -F. -f следит за дескриптором, то есть за самим открытым файлом. Когда logrotate переименовывает syslog в syslog.1, tail -f продолжает смотреть на этот переименованный файл, в который уже никто не пишет, и вывод просто замолкает. -F следит за именем: после ротации он замечает, что под именем syslog появился новый файл, и переключается на него. Для долгого слежения за логом на реальном сервере используйте -F.
Флаг | Что делает |
|---|---|
| Показать последние N байт. |
| Выводить поступающие данные по мере роста файла. Без значения используется |
| То же, что |
| Показать последние N строк вместо 10. |
| С |
| С |
| Не выводить заголовки с именами файлов |
| Продолжать пытаться открыть файл, даже когда он недоступен |
| С |
| Всегда выводить заголовки с именами файлов |
| Разделитель строк — NUL, а не перевод строки |
| Показать справку |
| Показать версию |
У N в -c и -n могут быть суффиксы-множители: b — 512, kB — 1000, K — 1024, MB — 10001000, M — 10241024, GB, G и так далее до Y, R, Q. Двоичные приставки тоже работают: KiB = K, MiB = M.
less
less — постраничный просмотр файла. Он не загружает файл целиком, поэтому спокойно открывает логи на гигабайты, и в нём можно двигаться вперёд и назад, искать, фильтровать строки. Это основной способ изучать большой лог, когда tail уже мало.
Выход — q, справка внутри программы — h. Режим слежения за файлом включается клавишей F внутри или запуском less +F файл: остановка по Ctrl+C позволяет пролистать историю, повторное F возвращает слежение. Клавиши, помеченные *, можно предварять числом N, оно меняет их поведение. Большинство ключей командной строки можно переключить и внутри less клавишей - (короткий) или -- (длинный).
В таблице ниже сначала идут ключи командной строки, затем клавиши внутри программы. Строки, относящиеся к работе внутри less, помечены словом «внутри».
Флаг | Что делает |
|---|---|
| Показать справку |
| Поиск пропускает текущий экран |
| Поиск начинается сразу после целевой строки |
| Количество буферов |
| Не выделять буферы автоматически для каналов |
| Перерисовывать экран очисткой, а не прокруткой |
| Режим «глупого» терминала |
| Задать цвета экрана |
| Выходить при достижении конца файла |
| Открывать и не обычные файлы |
| Выйти, если файл целиком помещается на первый экран |
| Подсвечивать только последнее найденное |
| Не подсвечивать найденное вообще |
| Предел прокрутки назад |
| Игнорировать регистр в поиске, если в шаблоне нет заглавных |
| Игнорировать регистр в любом поиске |
| Позиция найденной строки на экране |
| Показывать колонку состояния слева |
| Использовать файл lesskey |
| Выходить из |
| Игнорировать переменную окружения |
| Стиль подсказки внизу экрана |
| Не использовать номера строк ( |
| Копировать ввод в файл (только для стандартного ввода) |
| То же, но существующий файл перезаписывается без вопросов |
| Начать с первого совпадения с шаблоном |
| Задать собственную подсказку |
| Отключить звуковой сигнал терминала |
| Выводить управляющие символы как есть. Нужен для цветного вывода |
| Сжимать несколько пустых строк в одну |
| Обрезать длинные строки, а не переносить |
| Найти тег |
| Использовать другой файл тегов |
| Изменить обработку backspace |
| Показать версию |
| Подсвечивать первую новую строку после прокрутки экрана вперёд |
| Подсвечивать первую новую строку после любого движения вперёд |
| Задать позиции табуляции |
| Не использовать строки инициализации и деинициализации termcap (экран не очищается при выходе) |
| Предел прокрутки вперёд |
| Размер окна |
| Символы кавычек оболочки |
| Не показывать тильды после конца файла |
| Шаг горизонтальной прокрутки (0 — пол-ширины экрана) |
| Автоматически определять размер входного файла |
| Команда |
| Искать по мере ввода каждого символа шаблона |
| Ширина поля номера строки в |
| Включить ввод мышью |
| Не посылать строки инициализации и деинициализации клавиатуры termcap |
| Убрать повторы из истории команд |
| Символ, которым помечаются обрезанные строки |
| Сохранять закладки между запусками |
| Ширина колонки состояния |
| Следующие ключи используют обратную косую черту как экранирующий символ |
| Включить цветной текст |
| На сколько строк прокручивать за один щелчок колеса мыши |
| Показать справку |
| Выйти |
| На строку вперёд (или на N строк) |
| На строку назад (или на N строк) |
| На окно вперёд (или на N строк) |
| На окно назад (или на N строк) |
| На окно вперёд и задать размер окна N |
| На окно назад и задать размер окна N |
| На окно вперёд, не останавливаясь на конце файла |
| На полокна вперёд (и задать размер полокна N) |
| На полокна назад (и задать размер полокна N) |
| Вправо на пол-ширины экрана (или на N позиций) |
| Влево на пол-ширины экрана (или на N позиций) |
| Вправо до последнего показанного столбца |
| Влево до первого столбца |
| Следить вперёд бесконечно, как |
| Как |
| Перерисовать экран |
| Перерисовать экран, отбросив буферизованный ввод |
| Искать вперёд N-ю подходящую строку |
| Искать назад N-ю подходящую строку |
| Повторить предыдущий поиск (N-е вхождение) |
| Повторить предыдущий поиск в обратном направлении |
| Повторить предыдущий поиск, переходя между файлами |
| Повторить предыдущий поиск в обратном направлении между файлами |
| Включить или выключить подсветку найденного |
| Снять подсветку найденного |
| Показать только подходящие строки. Вернуть всё: |
| Искать строки, которые не подходят |
| Искать по нескольким файлам, переходя через конец файла |
| Начать поиск с первого файла (для |
| Подсветить совпадения, но не перемещаться |
| Не использовать регулярные выражения |
| Зациклить поиск, если совпадений не нашлось |
| В первую строку файла (или в строку N) |
| В последнюю строку файла (или в строку N) |
| В начало файла (или на N процентов вглубь файла) |
| К следующему тегу (N-му) |
| К предыдущему тегу (N-му) |
| Найти закрывающую скобку |
| Найти открывающую скобку |
| Найти закрывающую скобку |
| Найти открывающую скобку |
| Поставить закладку на верхнюю строку. Закладкой может быть любая буква |
| Поставить закладку на нижнюю строку |
| Перейти к закладке. Заранее определены |
| Вернуться на предыдущую позицию |
| То же, что |
| Снять закладку |
| Открыть другой файл |
| Следующий файл из командной строки (N-й) |
| Предыдущий файл из командной строки (N-й) |
| Первый файл из командной строки (или N-й) |
| Убрать текущий файл из списка командной строки |
| Показать имя текущего файла |
| Переключить ключ командной строки |
| Переключить ключ командной строки по длинному имени |
| Показать значение ключа |
| Показать значение ключа по длинному имени |
| Выполнять команду |
| Выполнить команду в оболочке |
| Передать участок файла между текущей позицией и закладкой X в команду оболочки |
| Сохранить ввод в файл |
| Открыть текущий файл в |
| Показать версию |
| Курсор на символ вправо |
| Курсор на символ влево |
| Курсор на слово вправо |
| Курсор на слово влево |
| Курсор в начало строки |
| Курсор в конец строки |
| Удалить символ слева от курсора |
| Удалить символ под курсором |
| Удалить слово слева от курсора |
| Удалить слово под курсором |
| Удалить всю строку |
| Предыдущая введённая команда |
| Следующая введённая команда |
| Дополнить имя файла и перебирать варианты |
| Дополнить имя файла и перебирать в обратном порядке |
| Дополнить имя файла и показать все варианты |
Окно по умолчанию равно высоте экрана, полокна — половине высоты. Строка команд — это строка внизу экрана, которую вы вводите, например, при поиске.
grep
grep ищет строки по шаблону. Он работает с текстовыми файлами и с выводом других команд через конвейер. Для логов это основной инструмент поиска: найти все неудачные входы, все строки одной службы, посчитать количество ошибок.
Общий вид: grep [ключи] ШАБЛОНЫ [ФАЙЛ...]. Шаблонов можно указать несколько, разделяя их переводом строки. Если файл указан как -, читается стандартный ввод. Если файл не указан, читается текущий каталог при -r и стандартный ввод в остальных случаях. Код завершения: 0, если что-то найдено, 1, если ничего не совпало, 2 при ошибках (если не задан -q).
Флаг | Что делает |
|---|---|
| Шаблоны — расширенные регулярные выражения |
| Шаблоны — обычные строки, без регулярных выражений |
| Шаблоны — простые регулярные выражения (режим по умолчанию) |
| Шаблоны — регулярные выражения Perl |
| Использовать указанные шаблоны для поиска |
| Брать шаблоны из файла |
| Игнорировать регистр |
| Учитывать регистр (режим по умолчанию) |
| Совпадение только с целым словом |
| Совпадение только с целой строкой |
| Строки разделяются нулевым байтом, а не символом конца строки |
| Не показывать сообщения об ошибках |
| Выбирать строки, которые не подходят |
| Показать версию |
| Показать справку |
| Остановиться после указанного числа совпавших строк |
| Печатать смещение в байтах вместе со строкой |
| Печатать номер строки вместе со строкой |
| Сбрасывать буфер после каждой строки. Нужен в конвейерах со слежением, иначе вывод приходит с задержкой |
| Печатать имя файла для каждой строки |
| Не печатать имя файла |
| Использовать метку в качестве имени файла для стандартного ввода |
| Показывать только совпавшие непустые части строк |
| Подавить весь обычный вывод |
| Как считать бинарный файл: |
| То же, что |
| То же, что |
| Как обрабатывать каталоги: |
| Как обрабатывать устройства, FIFO и сокеты: |
| То же, что |
| То же, но с переходом по всем символьным ссылкам |
| Обрабатывать только файлы, подходящие под маску |
| Пропускать файлы, подходящие под маску |
| Пропускать файлы, подходящие под маски из файла |
| Пропускать каталоги, подходящие под маску |
| Печатать только имена файлов без выбранных строк |
| Печатать только имена файлов с выбранными строками |
| Печатать только количество выбранных строк на файл |
| Выравнивать табуляцией, если нужно |
| Печатать нулевой байт после имени файла |
| Напечатать указанное число строк перед совпадением |
| Напечатать указанное число строк после совпадения |
| Напечатать указанное число строк вокруг совпадения |
| То же, что |
| Печатать SEP в строке между группами совпадений с контекстом |
| Не печатать разделитель между группами |
| Подсвечивать совпавшие строки: |
| Не удалять символы CR в конце строки (MS-DOS и Windows) |
zgrep
zgrep — это grep, который умеет читать сжатые gzip-файлы. Из-за ротации логи недельной давности лежат в syslog.2.gz, auth.log.3.gz и так далее, и обычный grep по ним ничего не найдёт. zgrep распаковывает их на лету и ищет внутри, а обычные несжатые файлы читает как grep. Поэтому одна команда по маске (/var/log/syslog*) охватывает и текущий лог, и все архивные.
Общий вид: zgrep [ключи] [-e] ШАБЛОН [ФАЙЛ...]. Порядок файлов при маске лексикографический, а не по времени: syslog.1, syslog.10.gz, syslog.2.gz. Для сжатия другими алгоритмами есть bzgrep (.bz2), xzgrep (.xz) и zstdgrep (.zst).
Ключи те же, что у grep (таблица выше). Не поддерживаются:
Флаг | Что делает в |
|---|---|
| Рекурсивный поиск с переходом по символьным ссылкам |
| Рекурсивный поиск |
| Действие над каталогами |
| Обрабатывать только файлы, подходящие под маску |
| Пропускать файлы, подходящие под маску |
| Пропускать файлы по маскам из файла |
| Пропускать каталоги, подходящие под маску |
| Печатать нулевой байт после имени файла |
| Строки разделяются нулевым байтом |
Из-за этого zgrep -r по каталогу не работает: файлы нужно перечислять явно или задавать маской оболочки.
Журналы входов: last, lastb, lastlog
Журналы входов в систему бинарные, и читать их можно только специальными командами, а не grep или less. last читает /var/log/wtmp: историю входов, выходов, перезагрузок и выключений. lastb читает /var/log/btmp: неудачные попытки входа. lastlog читает /var/log/lastlog: время последнего входа каждого пользователя. Исходные записи в текстовом виде показывает utmpdump, например sudo utmpdump /var/log/wtmp. last и lastlog работают без sudo, а lastb нужен sudo, потому что btmp закрыт для всех, кроме root и группы utmp.
Общий вид: last [ключи] [имя_пользователя...] [tty...], у lastb то же самое, у lastlog просто lastlog [ключи]. Ключи last и lastb одинаковые, отличается только файл по умолчанию: /var/log/wtmp у last и /var/log/btmp у lastb.
Команда | Ключ | Что делает |
|---|---|---|
|
| Сколько строк вывести |
|
| Имя хоста в последней колонке |
|
| Перевести IP-адрес обратно в имя хоста |
|
| Взять указанный файл вместо |
|
| Полное время и дата входа и выхода |
|
| IP-адреса в виде «числа и точки» |
|
| Сколько строк вывести |
|
| Не выводить поле с именем хоста |
|
| Строки начиная с указанного времени |
|
| Строки до указанного времени |
|
| Кто был в системе в указанное время |
|
| Полные имена пользователя и домена |
|
| Добавить записи о выключениях системы и смене уровня запуска |
|
| Формат меток времени: |
|
| Справка |
|
| Версия |
|
| Записи старше указанного числа дней |
|
| Очистить запись lastlog пользователя. Только вместе с |
|
| Справка |
|
| Каталог, в который выполняется chroot |
|
| Записать в lastlog пользователя текущее время. Только вместе с |
|
| Записи за последние указанные дни |
|
| Запись только для этой учётной записи |
Что чаще всего используется для разбора проблем
Вообще на практике многие ключи и флаги вы можете не встретить или не использовать, но гарантированно возникнет ситуация, когда вам понадобится сделать следующее:
вывести лог целиком до и после запуска N-го сервиса (например, чтобы посмотреть, что происходит при его запуске);
вывести последние, условно, 50 строк, чтобы посмотреть причину падения сервиса;
вывести только строки с нужным словом (например, со статусом err или warn и т.п.);
проверить на нехватку памяти (чтобы посмотреть, например, сработал ли OOM killer);
вывести логи полностью и т.п.
Попробуйте самостоятельно составить такие команды, если у вас развёрнут Docker или какой-нибудь другой сервис/служба. (Ну так, чисто для практики :) ) Если справились, то вы большой молодец!)
Заключение
В статье мы разобрали базовые утилиты для работы с логами и то, на чём они держатся: где лежат логи, чем текстовые отличаются от бинарных, что такое уровни важности, ротация и постоянный журнал journald. Для одного сервера или homelab этого набора хватает. Но бывают случаи потяжелее. Например, нужно сопоставить по времени сразу несколько логов разных служб, разобраться в файлах с разными форматами или перекопать гигабайты записей. Тут даже эти утилиты начинают мешать: вы гоняете один и тот же grep по десятку файлов и сшиваете результат руками. В таких ситуациях подключают инструменты вроде lnav: он сам разбирает форматы логов, склеивает несколько файлов в одну ленту по времени и читает сжатые архивы напрямую. Это уже тема для отдельной статьи.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.