Что делать, чтобы логи не заполнили весь диск? Рассказываем, как настроить ротацию логов с logrotate на Ubuntu 24.04, также приводим примеры настроек для веб-сервера, базы данных и приложения, которому не подходит ротация по времени.
Введение
В Ubuntu 24.04 логи системных и сервисных компонентов хранятся в /var/log/ и без ротации они со временем заполняют диск. Чтобы этого не происходило, нужно настроить автоматическую очистку старых логов. В системе за это отвечает logrotate — утилита, которая по заданным правилам архивирует, сжимает и удаляет журналы.
Как работает logrotate
logrotate — это стандартная утилита в Ubuntu 24.04, которая позволяет задать правила ротации для любых лог-файлов: системных, сервисных или кастомных. Её задача — регулярно проверять состояние журналов и, если выполняются заданные условия (размер, возраст, количество копий и т. д.), выполнять действия: переименование, сжатие, удаление и создание нового файла.
По умолчанию logrotate запускается ежедневно через системный cron-джоб /etc/cron.daily/logrotate. Этот скрипт может вызываться через systemd timer или напрямую cron, в зависимости от конфигурации.
При запуске logrotate:
- проверяет файлы, указанные в конфигурации;
- переименовывает текущий лог-файл, добавляя к имени постфикс (например, .1, .gz, .20250730);
- создаёт новый файл с тем же именем, чтобы приложение продолжило писать в него;
- сжимает старый файл в gzip (если указано compress);
- удаляет архивы, превышающие лимит по количеству (rotate) или по возрасту (maxage);
- выполняет скрипты до и после ротации (если заданы prerotate, postrotate, firstaction, lastaction).
Главный конфигурационный файл — /etc/logrotate.conf. Этот файл содержит глобальные параметры и директивы, применимые ко всем логам, если в других местах не указано иное. Пример содержимого:
weekly
rotate 4
create
compress
include /etc/logrotate.d
Здесь:
- weekly — ротация раз в неделю;
- rotate 4 — хранить 4 архивных копии;
- create — создавать новый пустой файл после ротации;
- compress — использовать gzip для старых логов;
- include /etc/logrotate.d — подключить дополнительные правила из этой директории.
/etc/logrotate.d/ — каталог с настройками ротации логов конкретных приложений, например:
- /etc/logrotate.d/nginx
- /etc/logrotate.d/mysql-server
- /etc/logrotate.d/rsyslog
Каждый файл описывает поведение logrotate для логов конкретного сервиса. Сначала в нём указывается путь к лог-файлам (или шаблон), затем внутри фигурных скобок — параметры ротации.
logrotate ведёт внутреннюю базу с временными метками — по умолчанию это файл /var/lib/logrotate-state. В нём хранятся последние даты ротации для каждого файла, что позволяет logrotate не дублировать работу и не трогать файлы чаще, чем нужно. Если этот файл удалить — при следующем запуске logrotate посчитает, что ни один лог ещё не ротировался, и выполнит ротацию для всех сразу (полезно, если нужно немедленно применить новые настройки).
Если в правилах указано compress, старые логи сжимаются через gzip сразу после ротации. Чтобы контролировать степень и время сжатия есть вспомогательные директивы:
- delaycompress — откладывает сжатие на один цикл ротации. То есть, при первой ротации файл переименовывается, но не сжимается (удобно, если приложение не сразу переключается на новый файл);
- compresscmd — позволяет указать другой метод сжатия (по умолчанию gzip, можно задать xz, zstd, bzip2).
Примеры настройки ротации логов
Ротация логов веб-сервера Nginx
logrotate по умолчанию умеет ротировать логи Nginx — при установке nginx-common создаётся файл /etc/logrotate.d/nginx. Но стоит проверить, актуальны ли параметры и, если нужно, адаптировать их под себя:
/var/log/nginx/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
postrotate
systemctl reload nginx
endscript
}
В этом конфиге:
- /var/log/nginx/*.log — указывает шаблон логов, которые нужно ротировать. В стандартной установке это access.log и error.log, но могут быть и другие — например, логи виртуальных хостов.
- daily — ежедневная ротация. Это актуально, если трафик стабильный и лог-файлы могут быстро разрастаться. Если логов мало, можно заменить на weekly — ротация раз в неделю.
- rotate 14 — хранить 14 архивных копий. В связке с daily это две недели логов, при weekly — это почти 4 месяца.
- compress — сжатие архивных файлов через gzip.
- delaycompress — сжимать не текущую ротацию, а предыдущую. Это важно для совместимости: приложения могут временно продолжать писать в уже переименованный файл, а не переключаться сразу на новый.
- missingok — не считать ошибкой, если лог-файл отсутствует.
- notifempty — не выполнять ротацию, если файл пуст.
- create 0640 www-data adm — после ротации создать новый пустой файл с такими параметрами:
- 0640 — права доступа (владелец может читать и писать, группа — только читать);
- www-data — владелец файла (веб-сервер);
- adm — группа, которая может просматривать логи.
Это важный параметр: если не задать create, лог-файл не будет пересоздан, и Nginx не сможет в него писать. А если задать неправильные права — веб-сервер может получить ошибку Permission denied.
- postrotate … endscript — блок postrotate исполняется после ротации. Здесь вызывается systemctl reload nginx — команда, которая заставляет Nginx перечитать конфигурацию и заново открыть лог-файлы. Если этого не сделать, Nginx продолжит писать в удалённый файл, открытый по файловому дескриптору, и ротация окажется бессмысленной.
Ротация логов PostgreSQL
PostgreSQL может быстро раздувать логи, особенно если активен SQL-логгинг или включено логирование медленных запросов.
Пример конфигурации для PostgreSQL 16:
/var/log/postgresql/*.log {
weekly
rotate 8
compress
sharedscripts
postrotate
pg_ctlcluster 16 main reload
endscript
}
Здесь:
- sharedscripts — logrotate запускает postrotate один раз для всех файлов из этого блока, а не для каждого по отдельности;
- postrotate … endscript — команда pg_ctlcluster перезапускает лог-файл, не затрагивая саму работу базы, 16 — версия PostgreSQL, а main — имя кластера (можно посмотреть через pg_lsclusters).
Ротация логов кастомных приложений
Собственные сервисы, особенно те, которые много пишут в STDOUT/STDERR или ведут логи по собственному формату, не всегда поддаются ротации по времени. В таких случаях удобно ротировать по размеру:
/opt/myapp/logs/*.log {
size 100M
rotate 5
compress
dateext
}
Параметры:
- size 100M — ротация файлов, достигших размера 100 мегабайт;
- dateext — добавляет дату в имя архива, например: app.log-20250730.gz. Это упрощает отладку и автоматический разбор логов по времени.
Если приложение не реагирует на ротацию (например, продолжает писать в старый файл), нужно либо добавить postrotate с systemctl reload myapp, либо использовать директиву copytruncate, которая копирует содержимое текущего лог-файла в архив и очищает исходный файл, а приложение при этом продолжает писать в тот же файл без перерыва. Однако использование copytruncate связано с риском: возможна потеря данных, если приложение продолжает писать в момент копирования.
Параметры logrotate
logrotate даёт возможность гибко управлять поведением ротации с помощью дополнительных директив:
- maxage — удаляет архивные лог-файлы по их возрасту, независимо от значения rotate. Например maxage 30 удалит все логи старше 30 дней. Если указаны оба параметра — rotate и maxage — будет применён более строгий.
- minsize — не ротировать лог-файл, если его размер меньше указанного. Удобно для случаев, когда периодическая ротация по дате не имеет смысла, если файл почти не содержит данных. Часто используется совместно с daily или weekly, чтобы избежать создания пустых архивов.
- dateformat, например dateformat -%Y%m%d, — используется вместе с директивой dateext, чтобы задать формат даты, добавляемой к имени архивного лог-файла. В этом примере архив может называться access.log-20250730.gz. Поддерживаются все стандартные элементы strftime:
- %Y — год;
- %m — месяц;
- %d — день;
- %H, %M, %S — часы, минуты, секунды (если нужно точное время).
- su (su appuser appgroup) — указывает, под каким пользователем и группой запускать ротацию для данного блока. Это критично в ситуациях, когда лог-файлы принадлежат не root, а какому-либо приложению (например, nginx, postgres, myapp) и имеют ограничения по доступу. Без su logrotate может не иметь прав на создание или изменение лог-файла после ротации, что приведёт к ошибкам.
- compresscmd / uncompresscmd — позволяют задать альтернативные утилиты для сжатия. По умолчанию используется gzip, но можно заменить на xz, zstd или bzip2, если нужны другие алгоритмы:
compresscmd /usr/bin/xz
uncompresscmd /usr/bin/unxz
- extension — задаёт расширение архивных файлов. Полезно, если сжатие отключено, но вы хотите отличать архивы по имени.
extension .bak
- ifempty — ротировать даже пустые логи (например, в тестовых средах).
- notifempty — не трогать пустые файлы.
- firstaction / lastaction — позволяют запускать скрипты один раз до/после всей серии ротаций. Например:
firstaction
echo "Ротация началась: $(date)" >> /var/log/rotate.log
endscript
Это удобнее, чем писать то же самое в каждый postrotate, особенно если обрабатывается сразу несколько файлов в одном блоке.
Проверка работоспособности и диагностика проблем
Перед тем как применять изменения в продакшене, проверьте конфиг на корректность. Это делается через ключ -d (dry-run), который только показывает, что будет выполнено, без реального запуска:
sudo logrotate -d /etc/logrotate.d/nginx
Команда выведет на экран, какие файлы будут ротироваться, что с ними произойдёт, какие команды будут вызваны (postrotate, compress и т. д.).
Чтобы выполнить ротацию принудительно, без ожидания следующего запуска cron, добавьте ключ -f (force):
sudo logrotate -f /etc/logrotate.conf
Можно указать конкретный файл:
sudo logrotate -f /etc/logrotate.d/nginx
Обратите внимание, что после -f создаются новые архивы и обновляется статус-файл (/var/lib/logrotate-state).
Чтобы найти «тяжёлые» логи, выполните:
sudo ncdu /var/log/
ncdu отображает дерево директорий в интерактивном виде, и вы сможете легко определить, какие файлы самые большие и какие директории переполнены.
Альтернативный способ через du:
sudo du -sh /var/log/* | sort -hr | head -20
Команда выведет 20 самых объёмных поддиректорий и файлов в /var/log/.
Для глубокого анализа полезно посмотреть внутренний статус-файл logrotate:
sudo cat /var/lib/logrotate-state
В этом файле хранятся последние даты ротации по каждому лог-файлу. Если нужного файла в списке нет — logrotate о нём не знает. Если есть, но дата старая — значит, ротация не запускалась и нужно искать причину.
Читайте в блоге:
- Как установить .deb-пакет на Ubuntu 24.04: все способы
- Удалённый рабочий стол на Ubuntu через VNC: пошаговая настройка
- Настройка NGINX на Ubuntu 24.04 LTS: от первого запуска до HTTPS