Читайте журналы построчно в бинарном режиме, фильтруйте строки и ротируйте результат до записи строки, которая превысит лимит 200 МБ.
Обработка и ротация файлов журналов Nginx
Читайте журналы построчно в бинарном режиме, фильтруйте строки и ротируйте результат до записи строки, которая превысит лимит 200 МБ.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Веб‑сервер Nginx сохраняет запросы в файл /var/log/nginx/access.log. Каждый день происходит ротация, поэтому в каталоге /var/log/nginx появляются несколько файлов:
- /var/log/nginx/access.log – текущий журнал;
- /var/log/nginx/access.log.1 – журнал за предыдущий день;
- /var/log/nginx/access.log.2 – журнал за два дня назад;
- /var/log/nginx/access.log.3 и т.д.
Ротация запускается в полночь, но размеры файлов могут сильно различаться – в зависимости от нагрузки за день. Требуется написать утилиту, которая будет сканировать все файлы журнала (access.log и *access.log.**) в указанной директории, искать в них строки, соответствующие заданному шаблону (например, при шаблоне «favicon.ico» следует вывести все строки, где встречается «favicon.ico»).
Найденные строки необходимо сохранять в файл /var/log/nginx/parsed/lines.txt. Размер этого файла не должен превышать 200 МБ. Как только размер достигает лимита, файл должен быть переименован в /var/log/nginx/parsed/lines.txt.1 (при последующих ротациях – в .2, .3 и т.д.), а затем создать новый пустой /var/log/nginx/parsed/lines.txt и продолжить запись.
Таким образом, при каждом достижении 200 МБ происходит очередная ротация результата, формируя последовательную нумерацию файлов в каталоге parsed.
Ответ
Читайте журналы построчно в бинарном режиме, фильтруйте строки и ротируйте результат до записи строки, которая превысит лимит 200 МБ.
Зафиксируйте список входных файлов перед обработкой, исключив каталог parsed. При необходимости обрабатывайте .gz через gzip. Размер измеряйте в байтах: для десятичных 200 МБ лимит равен 200_000_000.
Алгоритм записи совпавшей строки:
- Если сама строка больше лимита, сообщить об ошибке: сохранить её целиком с таким ограничением невозможно.
- Если
текущий_размер + размер_строки > лимит, закрытьlines.txt, переименовать в следующий свободныйlines.txt.Nи открыть новый. - Записать строку и обновить счётчик; при точном достижении лимита также выполнить ротацию.
Не перезаписывайте существующие архивы. Для однократного запуска достаточно последовательного чтения; для постоянного наблюдения нужны inode/offset и защита от повторной обработки при ротации Nginx. Обработку гигантских строк следует ограничить по памяти.