Где лежат логи сервиса
Каталог такого журнала закрыт от посторонних правами группы: без нужной группы чтение обрывается явным отказом в доступе, и отсутствие прав здесь видно сразу — пустотой вместо записей отвечает не файл, а системный журнал, о чём ниже.
Порядок здесь обратный привычному: сначала убедиться, что чужие записи вам вообще показывают, и только потом искать, куда они уходят на этой машине.
Четыре адреса вывода
Вывод сервиса оказывается по одному из четырёх адресов, и это разные владельцы с разными форматами строки и разными правилами ротации.
-
Файл, который приложение открыло само по своему конфигу. Веб-серверы и базы данных пишут в свои файлы мимо потоков. Каталог журнала закрыт от посторонних правами группы.
-
Файл в каталоге журналов, который написал демон системного протокола журналирования. На минимальных и облачных образах его может не быть вовсе — тогда привычного сводного файла в каталоге журналов не существует. Если демон установлен, он получает строки от приложений и записывает их в свой файл.
-
Журнал системы инициализации. Перехват стандартного вывода и потока ошибок — значение по умолчанию для юнита, но оно переопределяется в самом юните. Вывод можно направить в файл, дописывать в файл, обрезать файл при старте, отдать в сокет или выбросить в никуда. Пересылку в демон системного протокола журналирования включает сам журнал системы своей настройкой. Когда она включена, одна и та же строка лежит сразу в двух местах — в журнале системы и в файле демона, — в разном виде и с разными отметками времени, и вторая копия не новое событие, а та же строка.
-
Журнал контейнера, который ведёт движок контейнеров. Формат строки и правила ротации здесь свои и зависят от назначенного драйвера, а под оркестратором журнал ведёт не движок, а агент узла. Чем смотрят назначенный драйвер и действующий предел — ниже, в разделе «Контейнеры и место на диске».
Пустой вывод по юниту не означает отсутствия логов: сервис мог писать в свой файл, а не в потоки. Что объявил про свои потоки конкретный юнит, смотрят в его файле и в показанных системой итоговых свойствах этого юнита.
Права доступа
Учётная запись без нужной группы видит в системном журнале только собственные записи. Команда отрабатывает без ошибки и показывает пусто. Каталоги журналов веб-серверов закрыты от посторонних тем же способом — правами группы.
Сервис под управлением системы инициализации
Если потоки юнита всё-таки идут в журнал, остаются два вопроса: как долго строки там лежат и чем их оттуда отбирать. Ни один не решается поиском по слову — журнал подрезает себя сам, а фильтр по приоритету отделяет не ошибки приложения.
Хранение журнала
Хранение системного журнала бывает постоянным и временным. Какое на конкретной машине — видно по выставленному режиму хранения и по наличию каталога журнала на диске. Быстрая проверка того же — отбор по загрузке: у просмотрщика есть текущая, предыдущая и список всех.
Если перезагрузка была, а предыдущих загрузок в списке нет — хранение временное и доинцидентных строк не осталось. Если сервер с установки не перезагружали, пустой список про хранение не говорит ничего, и смотреть надо выставленный режим хранения и наличие каталога журнала на диске.
Даже постоянный журнал не вечен: он ограничен долей места файловой системы и подрезает себя сам. Сколько он занимает, сообщает сам просмотрщик, а действующий предел называет демон журнала в собственной записи при старте. У просмотрщика есть штатная команда подрезки по размеру и по возрасту. Чистка каталога журнала удалением файлов даёт аварию с удержанным дескриптором. Читают журнал не только на живой машине: просмотрщик открывает переданный каталог журнала, отдельные файлы журнала и корень чужой файловой системы, поэтому двоичный формат не мешает прочитать машину, которая не загружается или к которой доступ уже отозван.
Приоритет записей
У строк, которые обычный юнит печатает в стандартный вывод и в поток ошибок, приоритет одинаковый — тот, что задан настройкой уровня в юните. Журнал даже не хранит, из какого потока пришла строка. Другой приоритет строка получает только двумя способами: префиксом приоритета в начале строки, разбор которого включён, либо записью в журнал напрямую мимо потоков. Поэтому фильтр по приоритету не отделяет ошибки приложения.
Окно времени и сведение зон
У просмотрщика журнала сужение периода встроено: границы окна принимаются и абсолютной датой, и относительным выражением. У текстового файла такого инструмента нет — период вырезают построчной обработкой по префиксу отметки.
Просмотрщик журнала печатает отметки времени в местной зоне машины на момент показа, а не на момент записи. У него есть режим универсального времени и формат с явным смещением. В файле отметку ставит само приложение в своей зоне, и переопределить её командой просмотра нельзя.
Зона внутри контейнера задаётся его образом и окружением и от хозяйской машины не наследуется. Контейнер может жить в универсальном времени при местной зоне хозяина, и одно событие получает на одной машине две непохожие отметки.
Многострочные записи рвут построчную фильтрацию: отметку несёт только первая строка события. Она в окно попадает, а строки-продолжения отметки не содержат и из окна выпадают. На экране остаётся заголовок ошибки без следа стека, и кажется, что след не записан.
Ротация файлов
Ротаторов на машине три, и настраиваются они в разных местах: планово запускаемый ротатор файлов, собственная подрезка системного журнала по занимаемому месту, ротация журналов контейнеров, которую ведёт движок контейнеров или агент узла.
Сжатие повёрнутых копий — включаемая настройка ротатора файлов. Включено сжатие или нет — видно в конфиге: смотрят глобальный конфиг ротатора и конфиги отдельных пакетов рядом с ним. У сжатия есть отложенная форма, оставляющая самую свежую копию несжатой. Включена она или нет, видно там же, в конфиге.
Схем именования две — числовой суффикс и суффикс-дата, поэтому имя повёрнутой копии заранее не известно: искать надо не ожидаемое имя, а смотреть весь каталог рядом с активным файлом. При числовых суффиксах повёрнутые копии сортируются как текст, и копия с двузначным номером встаёт раньше копии с однозначным. Поэтому группу файлов читают явным перечислением от старых к новым, а не маской.
Живой журнал и пустой файл
Стратегий ротации файла две.
-
Переименовать и создать новый. Слежение по дескриптору остаётся на переименованном файле: пока процесс пишет туда, строки идут по-прежнему. Замирает оно навсегда в тот момент, когда процесс переоткроет журнал и уйдёт в новый файл, — сам на новый файл дескриптор не перейдёт. Нужен режим слежения по имени, который переоткрывает файл.
-
Скопировать и обнулить на месте. Узел файла тот же, слежение по дескриптору продолжает работать, но замечает укорачивание и читает файл сначала. Часть строк на стыке могла потеряться.
При стратегии «переименовать и создать новый» процесс пишет в переименованный файл до тех пор, пока ему не послан сигнал переоткрытия журнала. Если шага с сигналом в настройках ротации нет или сигнал уходит не тому процессу, новый файл остаётся нулевого размера, а записи копятся в копии с суффиксом. Проверяется сравнением времени последней записи в повёрнутой копии с текущим временем.
Контейнеры и место на диске
Какой драйвер назначен этому контейнеру и с какими параметрами, показывает осмотр контейнера средствами движка; умолчание для всех новых контейнеров лежит в конфиге демона движка. Под оркестратором действующий предел задан настройкой агента узла на самой машине, и смотреть надо её, а не движок; там же, у агента узла, есть и отбор предыдущего экземпляра — в разборе падения по кругу смотреть надо именно его.
Отсутствие предела у журнала контейнера — свойство конкретного драйвера. У файлового драйвера в формате JSON ограничения нет, у второго штатного локального драйвера предел размера и число копий заданы из коробки. Под оркестратором файл режет агент узла со своими пределами.
Файл журнала привязан к идентификатору экземпляра, поэтому пересоздание контейнера заводит новый файл, а старый уходит вместе с экземпляром. Что делает перезапуск, зависит от того, кто ведёт файл: у движка контейнеров перезапуск остаётся в том же файле, у агента узла оркестратора каждый запуск получает свой файл, а предыдущий сохраняется.
Разросшийся файл журнала обнуляют, а не удаляют: после удаления имени в файловой системе нет и обнулять нечего, а место не вернётся, пока файл держит открытым работающий процесс. После удаления путей три — обнулить файл через дескриптор в служебной файловой системе процессов, послать сервису сигнал переоткрытия журнала или перезапустить процесс. Здесь разобран только тот случай, когда диск выедают журналы; порядок проверки самих ресурсов сервера — процессора, памяти, диска и сети — в материале Сервер тормозит: команды первой минуты.
Место по показаниям есть, а запись не проходит: повёрнутые копии выедают не байты, а учётные записи файлов. Разбор этого случая — в материале Место на диске кончилось, а удалять нечего.
Тупик
Открывают самый свежий файл в каталоге журналов и ищут в нём слово «error». Не помогает сразу по трём причинам:
- Юнит может вообще не писать в файл.
- Нужное время могло уехать в повёрнутую копию с непредсказуемым именем.
- Пустой вывод мог быть следствием прав.
Позиция редакции
Чтение логов начинается со сведения времени и сужения окна, а не с поиска слова. Сначала одно и то же время у жалобы, у балансировщика и у сервиса, потом период в несколько минут вокруг отказа, и только потом текстовый фильтр внутри него. Кто начинает с поиска по слову, читает совпадения из другого инцидента и чинит не то.
Неверна эта позиция, если журнал сервиса за смену умещается в несколько экранов. Там чтение подряд быстрее любой фильтрации и заодно показывает соседние строки, которые фильтр отрезал бы.