Ротация логов: типичные ошибки, которые съедают диск
Логrotate запустился, архивы появились, а свободное место всё равно исчезает. Разбираем, почему приложение продолжает писать в старый файл, когда опасен copytruncate и почему срок хранения не задаёт жёсткий лимит на диск.

Архивы есть, а диск всё равно заполняется
Ротация срабатывает, файл получает суффикс .1, но процесс продолжает писать в него — или логи растут быстрее, чем успевают архивироваться и удаляться. В итоге вы платите за переполненный диск простоем сервиса и временем на срочную очистку. Ниже — практика для Linux: примеры конфигурации ориентированы на logrotate 3.21.0, а конкретное поведение приложения нужно сверять с его документацией.
Сначала выясните, кто управляет файлами
Одна и та же папка может содержать логи, которыми управляют разные системы. Файлы в /var/log часто обрабатывает logrotate. Сообщения, которые сервис отправляет в systemd journal, ограничивают настройками journald. А в контейнерной среде ротация stdout и stderr может зависеть от настроек контейнерного движка. Не настраивайте несколько механизмов на одни и те же файлы: получится двойное перемещение или удаление.
Проверьте, что именно занимает место: общий размер файлов, число архивов, свободное пространство файловой системы и владельца процесса, который пишет в лог. На Linux переименование файла не закрывает его для процесса: у процесса остаётся открытый файловый дескриптор, связанный со старым файлом. Это ключ к самой частой ошибке.
Термин. Открытый дескриптор — ссылка, через которую процесс продолжает читать или записывать файл. После переименования имя меняется, но уже открытый дескриптор сам собой не переключается на новый файл.
Три подхода — и цена каждого
| Подход | Когда подходит | Риск и цена |
|---|---|---|
| Переименовать файл и попросить приложение открыть новый | Приложение умеет перечитывать конфигурацию или переоткрывать лог по сигналу | Нужно проверить именно поведение приложения и не потерять связь между ротацией и переоткрытием |
copytruncate | Приложение нельзя заставить переоткрыть файл | Между копированием и обнулением часть записей может потеряться; копия временно занимает дополнительное место |
| Ограничивать journald | Сервис пишет в systemd journal, а не в отдельный файл | Параметры не управляют файлами, которые приложение пишет напрямую |
Ротация — это не просто переименование файла. Важно, чтобы писатель перешёл на новый файл, а старые данные получили понятный срок хранения.
Ошибки, из-за которых место не освобождается
Приложение продолжает писать в переименованный лог
Logrotate переименовал app.log в app.log.1 и создал новый app.log. Но приложение держит старый файл открытым. Новый лог остаётся пустым, а старый архив продолжает увеличиваться. Иногда удалённый файл уже не виден в каталоге, но продолжает занимать место, пока процесс не закроет его.
Для такого приложения после ротации нужен предусмотренный разработчиком способ переоткрыть журнал. Это может быть сигнал, команда или перезапуск — универсального варианта нет. Не посылайте сигнал наугад: он может завершить процесс или запустить другое действие.
Выбрали copytruncate и приняли его за безрисковый вариант
copytruncate копирует текущий файл, а затем обнуляет исходный. Приложение при этом продолжает писать в прежний файл, поэтому не требуется переоткрытие. Но записи, появившиеся после копирования и до обнуления, могут не попасть ни в архив, ни в новый лог. Копия также временно требует дополнительного места — при почти полном диске это важно.
Используйте этот режим только если приложение не умеет переоткрывать файл и потеря небольшого фрагмента лога приемлема. Если журнал нужен для расследования инцидентов или аудита, сначала проверьте другой способ.
Поставили срок хранения и решили, что места хватит
Директива rotate 14 задаёт число хранимых ротаций, а не максимальный объём в гигабайтах. Если файлы растут быстрее, четырнадцать архивов всё равно могут занять весь раздел. Даже maxsize не является мгновенным ограничителем: logrotate проверит условие при очередном запуске. Если проверка выполняется раз в сутки, за это время лог может вырасти критически.
Слишком широкий шаблон захватывает лишние файлы
Проверьте, какие пути подходят под маску в конфигурации. Шаблон для приложения не должен неожиданно захватывать чужие журналы или уже созданные архивы. Для проверки перед изменением настроек запустите logrotate в режиме отладки: он показывает план действий, не выполняя ротацию.
Настройка logrotate для приложения
Ниже — пример для logrotate 3.21.0. Он рассчитан на приложение, которое документированно открывает лог заново после сигнала HUP. Замените путь, имя systemd-службы, пользователя и группу на значения вашей системы. Если приложение не поддерживает такой сигнал, не копируйте команду переоткрытия: выберите способ из его документации.
/var/log/myapp/*.log {
daily
rotate 14
maxsize 200M
missingok
notifempty
compress
delaycompress
create 0640 myapp adm
sharedscripts
postrotate
systemctl kill --signal=HUP --kill-whom=main myapp.service
endscript
}
daily задаёт периодическую проверку, maxsize просит ротировать файл при превышении порога во время такой проверки, а rotate 14 ограничивает число архивов. delaycompress откладывает сжатие последнего архива до следующей ротации. Пользователь и группа в create должны совпадать с теми, под которыми приложение может писать в файл; иначе после ротации сервис может потерять доступ.
Сначала проверьте конфигурацию без изменений на диске: logrotate --debug /etc/logrotate.d/myapp. Посмотрите, какие файлы попали под правило и планируется ли ротация. После применения отдельно убедитесь, что новый файл создан с нужными правами, приложение пишет именно в него, а старый архив перестал расти.
Если логи идут в systemd journal
Не добавляйте файлы journal в правило logrotate. Их обслуживает journald. В конфигурации journald можно задать, например, SystemMaxUse=1G и SystemKeepFree=5G: первое ограничивает объём системного журнала, второе задаёт объём, который следует оставить свободным на файловой системе. Это не точный прогноз потребления всего диска и не замена мониторингу: настройка относится к журналу, а место нужно учитывать вместе с приложениями, базами и временными файлами.
Если сервис пишет в обычный файл, лимиты journald его не защитят. Если приложение запускается в контейнере и пишет в stdout или stderr, выясните, где хранятся эти потоки и какой механизм их ограничивает. Настраивайте ротацию на уровне фактического владельца логов, а не по названию каталога.
Как выбирать и что проверять
- Приложение умеет переоткрывать файл. Настройте обычную ротацию и документированный сигнал или команду. Проверка: после тестовой ротации новые записи появляются в новом файле.
- Переоткрытие невозможно, а небольшой пробел в логах допустим. Рассмотрите
copytruncate. Проверка: оцените временный расход места и сравните записи до и после теста; учитывайте, что полностью исключить потерю записей этот режим не обещает. - Сервис пишет в journal. Ограничьте journald и настройте оповещения о свободном месте. Проверка: убедитесь, что журнал ограничен, а отдельные файлы приложения не растут вне него.
- Запас диска мал или лог растёт рывками. Не полагайтесь только на ежедневный запуск logrotate. Учащайте проверку с учётом нагрузки, следите за свободным местом и заранее задайте порог оповещения.
Перед запуском проверьте версию командой logrotate --version: настройки могут отличаться в старых пакетах. Конфигурацию, особенно сигналы и права доступа, сначала испытывайте на одном сервисе и в безопасное время.
Что делать дальше
После настройки измеряйте не только размер каталога логов. Следите за свободными байтами на файловой системе, скоростью роста журналов и файлами, которые удалили, но процесс всё ещё держит открытыми. Проверьте эти показатели во время пикового трафика: ротация, которая справляется ночью, может не успеть днём. Если растёт именно объём записей, следующий шаг — найти источник шума и решить, какие события действительно нужно хранить.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: Руководство logrotate, Документация systemd-journald.conf
Частые вопросы
Почему файл app.log.1 продолжает расти после ротации?
Можно ли всегда включать copytruncate?
Гарантирует ли rotate 14, что логи займут не больше заданного объёма?
Что делать, если после ротации приложение перестало писать в лог?
Достаточно ли ограничить journald, чтобы защитить весь диск?
Как понять, что конфигурация logrotate подходит моей версии?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.