Выборочное чтение журналов
Мы уже умеем направлять вывод в файл. Теперь выберем, какой вывод стоит сохранять. Большой журнал может содержать тысячи успешных запросов и всего несколько строк, относящихся к жалобе пользователя. Полная копия усложняет чтение и увеличивает объём передаваемых данных. Цель диагностики — сформулировать вопрос, выбрать область наблюдения и сохранить достаточно контекста для объяснения результата.
В fixtures/access.tsv находится синтетический журнал DeskQueue. Его строки имеют время, статус, метод, путь, длительность и идентификатор запроса. Разделитель — табуляция. Значения подготовлены для обучения и не получены от работающего приложения. На их примере научимся читать начало, конец и найденные фрагменты, не меняя исходный файл.
Начало раскрывает договор данных
Перед поиском посмотрите заголовок и несколько строк. Это помогает увидеть порядок столбцов, формат времени и наличие пустых полей. Одинаковый поиск по двум журналам может дать разные результаты просто потому, что один из них имеет другой формат.
head -n 4 fixtures/access.tsv
wc -l fixtures/access.tsv
Число строк включает заголовок. Оно не равно числу пользовательских действий: один экран может сделать несколько запросов, а повтор операции создаст ещё одну запись. Даже правильный подсчёт строк отвечает только на ограниченный вопрос. Если позже понадобится число пользователей или заявок, потребуются другие данные и другое правило подсчёта.
У учебной таблицы есть фиксированный набор полей, но у настоящего приложения договор журнала может измениться после выпуска. Поэтому в evidence/log-reading.md запишите имя файла и его формат. При сравнении двух наблюдений проверьте, совпадает ли структура. Без этого различие в выборке можно ошибочно принять за изменение поведения приложения.
Конец файла и конец интересующего периода
Команда tail -n 4 показывает последние четыре строки файла. Если записи добавляются в порядке поступления, это полезный срез последних событий. Но «последнее в файле» и «последнее по времени события» не всегда совпадают. Отложенная доставка, объединение источников или повторная запись могут изменить порядок. Временное поле всё равно нужно читать.
tail -n 4 fixtures/access.tsv
tail -n 4 fixtures/access.tsv > evidence/access-last-four.tsv
Параметр tail -f позволяет следить за добавлением данных в открытый файл. Для журналов, которые переименовываются при ротации, может быть полезен tail -F, следящий за именем и повторяющий открытие. Эти режимы не превращают файл в полноценную систему наблюдения: после разрыва сеанса вы можете пропустить часть событий. Для длительного хранения нужен отдельный договор сбора.
В нашей неизменной таблице режим слежения не даст новых записей. Поэтому не ждите их как результата урока. Для понимания достаточно представить, что приложение дописывает строку после завершения запроса. Когда перейдём к systemd, рассмотрим чтение живого журнала службы с явным временным ограничением, а не бесконечное ожидание в учебной папке.
Ищем буквальный фрагмент
Начнём с имени ресурса. Параметр -F означает поиск буквального текста, а -n добавляет номер строки. Это удобно, когда часть пути содержит символы, имеющие специальный смысл в регулярном выражении. Не требуется изучать весь язык шаблонов, чтобы найти известный идентификатор.
grep -Fn '/api/tickets' fixtures/access.tsv
grep -Fn 'req-005' fixtures/access.tsv
Первая выборка показывает запросы к указанному пути и его вариантам, потому что поиск выполняется по вхождению текста. Она может включить /api/tickets/3 и даже другой столбец, если там случайно окажется такая строка. Вторая выборка использует идентификатор конкретного запроса. Выбирайте критерий по задаче и называйте его в описании, чтобы вывод нельзя было принять за строгую выборку по полю.
grep возвращает отдельный статус, когда совпадений нет, и другой ненулевой статус при ошибке чтения. Для человека пустой вывод похож в обоих случаях, поэтому позже сценарий будет учитывать код завершения. Сейчас сравните отсутствие известного файла и отсутствие слова в существующем файле. Причина пустого результата различается, хотя на экране может не быть полезных строк.
Контекст объясняет последовательность
У найденной строки иногда важны соседние записи. Например, ошибка могла появиться после успешного входа или повторного запроса. Параметр -C добавляет строки до и после совпадения. Сохраним небольшой срез вокруг учебного идентификатора.
grep -Fn -C 2 'req-005' fixtures/access.tsv > evidence/request-context.txt
Такой срез выражает соседство в файле, а не причинную связь. Соседние запросы могут принадлежать разным пользователям и процессам. Для нашего журнала идентификатор связывает одну запись; в приложении с несколькими событиями одного запроса полезен общий correlation id. Без него последовательность строк помогает ориентироваться, но не позволяет уверенно восстановить полную историю операции.
Номера строк удобны для разговора о конкретной копии файла. После ротации или фильтрации они могут измениться. Поэтому сохраните сам срез и признаки события: время, путь и идентификатор. Указание «ошибка на строке 14» без копии журнала плохо переносится между участниками. Запись «req-005, создание заявки, выбранный интервал» даёт больше устойчивого контекста.
Почему не ищем статус как случайное число
Команда grep '500' может найти код ответа, часть длительности, номера заявки или идентификатора. Увидев результат, легко объявить все строки серверными ошибками. Для учебной таблицы статус находится во втором столбце, поэтому следующий урок будет выбирать его как поле через awk. Пока цель — заметить ограничение текстового поиска, а не построить преждевременный отчёт.
Для буквального слова в обычном сообщении grep подходит хорошо. Для структурированного JSON лучше использовать парсер формата, а для табличного текста — инструмент, понимающий его разделитель. Выбор зависит от договора входных данных. Если формат меняется, хрупкий шаблон может молча перестать находить нужные события, хотя приложение продолжит записывать их.
В справке grep для Ubuntu описаны варианты поиска и статусы завершения. Пользуйтесь ими для уточнения конкретного поведения. Сам по себе длинный набор параметров не делает выборку точнее: точность начинается с объяснения, почему выбранный признак соответствует нашему вопросу.
В результате у нас есть маленький читаемый срез, а в описании указаны источник, критерий и ограничения. Мы различаем поиск фрагмента и выбор поля, соседство и связь событий, отсутствие совпадений и ошибку чтения. Дальше преобразуем табличный журнал в краткий отчёт по статусам и путям, сохранив исходные записи для проверки рассуждения.