Ротация журнала VPN-сторожа без поломки пишущего процесса
Сначала выберите приёмник, затем приведите ротацию в соответствие с тем, как процесс открывает файл: переименование для коротких проверок, повторное открытие или copytruncate для демона.
Проверка состояния VPN, которая каждую минуту дописывает строку, тихо создаёт вторую обязанность: решить, как эти строки покидают диск. Починка туннеля для этой обязанности ничего не делает, а переименование файла не перенаправляет процесс, который всё ещё держит старый дескриптор. Сначала ответьте на вопрос о приёмнике, затем приведите ротацию в соответствие с тем, как процесс открывает файл.
Выберите приёмник до политики ротации
Модуль systemd, который уже отправляет вывод в журнал, держит хранение в одном месте. journald применяет ограничения вроде SystemMaxUse и MaxRetentionSec , поэтому сторож, который пишет туда, наследует границу без лишней работы. Добавление второго неограниченного файла рядом удваивает обслуживание без пользы.
Отдельный файл оправдывает себя, когда его читает что-то ещё: парсер, выгрузка аудита или страница, ожидающая стабильного пути. После этого решения файлу нужны владелец, режим и политика ротации, записанные вместе, потому что все три верны только как набор. Путь, который может создать кто угодно, — это и путь, который может заменить кто угодно, поэтому права каталога относятся к той же заметке. Запишите всё это рядом с проверкой, и следующая правка начнётся с тех же фактов.
Напишите блок под пишущий процесс
Начните с процесса, который открывает путь при каждом вызове, дописывает строку и завершается. Этот шаблон переживает ротацию без всякого содействия процесса, потому что следующий запуск открывает файл, который сейчас лежит по этому пути. Блок ниже хранит неделю версий и заново создаёт файл с владельцем и режимом, которые нужны процессу:
/var/log/vpn-watchdog.log {
daily
rotate 7
create 0600 root root
missingok
notifempty
}
Руководство logrotate определяет число как количество сохраняемых повёрнутых версий, а не как гарантию семи дней истории, а ключевое слово daily оценивается при запуске задания, а не действует как собственный планировщик. В большинстве дистрибутивов этот вызов уже принадлежит таймеру systemd или записи cron, поэтому проверьте, какая существует, прежде чем добавлять вторую. Совпадение владельца важнее числа хранения. Копирование режима только для root на файл, который пишет служебная учётная запись, останавливает журналирование при следующей ротации, и сбой проявляется через часы как устаревшая отметка времени, а не как ошибка. Подтвердите пользователя процесса, прежде чем копировать блок откуда-то ещё.
Процессу, который никогда не переоткрывает файл, нужна другая мера
Долгоживущий процесс, держащий открытый дескриптор, продолжает писать в переименованный inode. Место не освобождается, и видимый файл перестаёт расти, что выглядит как сломанная ротация, пока вы не проверите inode. Либо научите процесс открывать файл заново, либо заставьте ротацию копировать и обрезать вместо переименования.
Путь с повторным открытием чище там, где программное обеспечение его поддерживает: отправьте документированный сигнал или выполните документированную команду, и пусть процесс сам откроет новый файл. Альтернатива — copytruncate , которая копирует содержимое под повёрнутое имя, а затем обрезает оригинал на месте, так что дескриптор остаётся действительным, но записи, попавшие между копированием и обрезкой, теряются.
Для модулей, запускаемых systemd, направьте StandardOutput в журнал или в файл и передайте модулю владение жизненным циклом. Цикл shell, который дописывает через tee -a без ограничения размера, — это та схема, которая во время сбоя заполняет раздел, потому что неудачная проверка часто пишет гораздо больше, чем здоровая.
Проверьте ротацию, не дожидаясь таймера
Режим отладки сообщает, что произошло бы, и ничего не трогает, что делает его безопасным первым запуском после правки. Когда будете довольны, принудительно выполните настоящую ротацию, затем убедитесь, что следующая строка журнала попадает в новый файл, а не в переименованный:
logrotate -d /etc/logrotate.d/vpn-watchdog logrotate -f /etc/logrotate.d/vpn-watchdog ls -l /var/log/vpn-watchdog.log* tail -n 3 /var/log/vpn-watchdog.log df -h /var/log
Читайте вывод в этом порядке. Проход отладки должен назвать файл и предполагаемые действия; принудительный запуск должен создать ожидаемое повёрнутое имя; tail должен показать свежую запись после повторного запуска процесса. Растущее значение df при уменьшающемся видимом файле означает описанную выше проблему с дескриптором.
Повторите принудительный запуск дважды, чтобы увидеть, как ведёт себя хранение, когда версии уже существуют. Удаление самого старого файла — ожидаемый результат, а отсутствие удаления обычно означает, что число или подстановочный знак в повёрнутом имени не совпадают с тем, что создал logrotate.
Сохраните откат и письменный отчёт
Сохраните предыдущий блок перед правкой и отметьте, какой планировщик его запускает, потому что откат, который восстанавливает файл, но не таймер, воспроизводит половину исходной проблемы. После восстановления поверните один раз вручную, затем убедитесь, что учётная запись процесса может писать по пути журнала. Если служба работает под systemd, перезагрузите модуль после любого изменения перенаправления его вывода, потому что работающий процесс продолжает писать в старую цель. Прочитайте следующие несколько строк журнала сами, вместо того чтобы полагаться на чистый возврат модуля.
Запишите режим, владельца, число хранения и ожидаемый дисковый бюджет рядом с самой проверкой. Когда позже проверка превратится из одноразового скрипта в демон, политика ротации должна измениться вместе с ней, и эта заметка скажет следующему человеку, какое предположение сломалось.
Наконец, держите решение о журнале отдельно от решения о восстановлении. Неудачная проверка должна следовать собственной политике восстановления соединения, а не правилу, спрятанному внутри logrotate, и никакая организация журналирования не должна быть причиной перезапуска работающего туннеля.