Настройка ротации логов Nginx в Ubuntu
Пошаговая настройка ротации access.log и error.log Nginx через logrotate с проверкой, хранением архивов и безопасным принудительным запуском.
Журналы Nginx постоянно увеличиваются по мере поступления запросов и появления ошибок. Без ротации файлы access.log и error.log могут занять значительную часть диска.
В Ubuntu для автоматической ротации журналов обычно используется logrotate.
В этой инструкции рассматривается только настройка и проверка ротации логов Nginx.
Проверено на: Ubuntu Server 24.04 LTS
Уровень сложности: начальный
Время выполнения: около 15–20 минут
Требуемый доступ: пользователь с правамиsudo
Что будет настроено
После выполнения инструкции:
- будет проверена стандартная конфигурация logrotate для Nginx;
- будут настроены периодичность и срок хранения;
- старые журналы будут сжиматься;
- будет проверено корректное переоткрытие логов Nginx;
- будет выполнен безопасный тест;
- будет показана ротация отдельных журналов виртуального хоста;
- будут разобраны типичные ошибки.
Основные журналы Nginx
Стандартные файлы:
/var/log/nginx/access.log
/var/log/nginx/error.log
Для отдельных виртуальных хостов могут использоваться:
/var/log/nginx/example.com.access.log
/var/log/nginx/example.com.error.log
Проверьте каталог:
sudo ls -lah /var/log/nginx/
Проверка размера журналов
sudo du -h /var/log/nginx/*
Сортировка по размеру:
sudo du -ah /var/log/nginx/ |
sort -h |
tail -20
Проверка свободного места
df -h
Проверьте файловую систему, где расположен:
/var/log
Если корневой раздел почти заполнен, сначала освободите место и только потом запускайте принудительную ротацию.
Проверка пакета logrotate
dpkg -l |
grep logrotate
Проверьте версию:
logrotate --version
Если пакет отсутствует:
sudo apt update
sudo apt install -y logrotate
Проверка стандартной конфигурации Nginx
sudo cat /etc/logrotate.d/nginx
На стандартной установке Ubuntu пакет Nginx обычно создаёт отдельный файл:
/etc/logrotate.d/nginx
Типовая конфигурация
Она может выглядеть примерно так:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /run/nginx.pid ]; then
kill -USR1 $(cat /run/nginx.pid)
fi
endscript
}
Конкретное содержимое зависит от пакета и версии Ubuntu.
Разбор параметров
daily
daily
Ротация выполняется ежедневно.
Альтернативы:
weekly
monthly
rotate
rotate 14
Хранить 14 архивных копий.
При ежедневной ротации это примерно две недели истории.
compress
compress
Старые журналы сжимаются через gzip.
Пример:
access.log.2.gz
delaycompress
delaycompress
Самый свежий архив не сжимается сразу.
Пример:
access.log.1
access.log.2.gz
Это удобно, если процесс ещё может кратковременно держать старый файл открытым.
missingok
missingok
Отсутствие журнала не считается ошибкой.
notifempty
notifempty
Пустой файл не ротируется.
create
create 0640 www-data adm
После ротации создаётся новый файл с указанными:
- правами;
- владельцем;
- группой.
Проверьте фактические права существующих файлов:
sudo stat /var/log/nginx/access.log /var/log/nginx/error.log
sharedscripts
sharedscripts
Секция postrotate выполняется один раз для всей группы файлов, а не отдельно для каждого журнала.
postrotate
После переименования логов Nginx должен закрыть старые файловые дескрипторы и открыть новые.
Обычно используется сигнал:
USR1
Пример:
kill -USR1 "$(cat /run/nginx.pid)"
Это не останавливает веб-сервер.
Почему нельзя просто переименовать лог
Если только переименовать:
access.log → access.log.1
процесс Nginx может продолжить писать в старый открытый файл.
Поэтому после ротации необходимо выполнить переоткрытие журналов.
Проверка PID Nginx
cat /run/nginx.pid
Проверьте процесс:
ps -fp "$(cat /run/nginx.pid)"
Создание резервной копии конфигурации
sudo cp /etc/logrotate.d/nginx /etc/logrotate.d/nginx.backup-$(date +%F-%H%M%S)
Проверьте:
sudo ls -l /etc/logrotate.d/nginx*
Рекомендуемая базовая политика
Для обычного небольшого сайта:
daily
rotate 14
compress
delaycompress
notifempty
Это обеспечивает около двух недель ежедневных журналов.
Хранение за 30 дней
daily
rotate 30
Старые файлы будут храниться примерно месяц.
Еженедельная ротация
weekly
rotate 8
Это примерно восемь недель истории.
Для активных сайтов еженедельная ротация может создавать слишком большие файлы.
Ротация по размеру
Можно добавить:
size 100M
Но size меняет логику запуска относительно временных директив.
Для сценария «ежедневно или при достижении размера» используется:
maxsize 100M
Пример:
daily
maxsize 100M
rotate 14
Разница size и maxsize
size
Ротация выполняется только при достижении указанного размера.
Временной интервал может фактически игнорироваться.
maxsize
Позволяет выполнить ротацию раньше планового срока, если файл стал слишком большим.
Для ежедневной политики обычно удобнее maxsize.
Пример итоговой конфигурации
/var/log/nginx/*.log {
daily
maxsize 100M
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /run/nginx.pid ]; then
kill -USR1 $(cat /run/nginx.pid)
fi
endscript
}
Перед применением проверьте владельца и группу журналов на своём сервере.
Проверка синтаксиса logrotate
sudo logrotate -d /etc/logrotate.d/nginx
Параметр:
-d
включает debug mode.
В этом режиме реальные файлы не ротируются.
Расширенный debug
sudo logrotate -dv /etc/logrotate.d/nginx
Проверьте:
- какие файлы найдены;
- нужна ли ротация;
- какой шаблон применяется;
- нет ли ошибки синтаксиса;
- корректен ли
postrotate.
Проверка общей конфигурации
sudo logrotate -d /etc/logrotate.conf
Это проверяет все подключённые правила.
Проверка state-файла
Logrotate хранит дату последней ротации в state-файле.
Обычно:
/var/lib/logrotate/status
Проверьте:
sudo grep nginx /var/lib/logrotate/status
Формат может отличаться в зависимости от версии.
Принудительный тест
Перед тестом проверьте текущие файлы:
sudo ls -lah /var/log/nginx/
Запустите:
sudo logrotate -f /etc/logrotate.d/nginx
Параметр:
-f
принудительно выполняет ротацию.
Проверка результата
sudo ls -lah /var/log/nginx/
Ожидаются файлы:
access.log
access.log.1
error.log
error.log.1
При следующем цикле старые файлы будут сжаты.
Проверка записи в новый журнал
Создайте запрос:
curl -I http://127.0.0.1
Проверьте:
sudo tail -5 /var/log/nginx/access.log
Новая запись должна появиться в текущем access.log, а не в access.log.1.
Проверка открытых файлов процесса
sudo lsof -p "$(cat /run/nginx.pid)" |
grep '/var/log/nginx'
Также проверьте worker processes:
pgrep nginx
sudo lsof -c nginx |
grep '/var/log/nginx'
Активные процессы должны писать в текущие файлы без суффикса .1.
Проверка службы logrotate
В современных системах logrotate обычно запускается через systemd timer.
Проверьте:
systemctl status logrotate.timer --no-pager
Проверьте автозапуск:
systemctl is-enabled logrotate.timer
Следующий запуск
systemctl list-timers --all |
grep logrotate
Проверка журнала systemd
sudo journalctl -u logrotate.service -n 100 --no-pager
Проверка timer:
sudo journalctl -u logrotate.timer -n 100 --no-pager
Ручной запуск общей службы
sudo systemctl start logrotate.service
Проверьте:
systemctl status logrotate.service --no-pager
Служба обычно имеет состояние:
inactive (dead)
после успешного разового выполнения. Это нормально для oneshot-сервиса.
Отдельные журналы виртуальных хостов
Если в Nginx настроено:
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
шаблон:
/var/log/nginx/*.log
обычно включает эти файлы автоматически.
Проверьте debug-режимом:
sudo logrotate -d /etc/logrotate.d/nginx |
grep example.com
Журналы в другом каталоге
Если сайт пишет в:
/var/log/nginx/example.com/access.log
стандартный шаблон:
/var/log/nginx/*.log
не захватит вложенный каталог.
Создайте отдельное правило.
Отдельное правило для каталога сайта
Создайте:
sudo nano /etc/logrotate.d/nginx-example
Добавьте:
/var/log/nginx/example.com/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /run/nginx.pid ]; then
kill -USR1 $(cat /run/nginx.pid)
fi
endscript
}
Проверка отдельного правила
sudo logrotate -d /etc/logrotate.d/nginx-example
Принудительный тест:
sudo logrotate -f /etc/logrotate.d/nginx-example
Исключение дублирующихся шаблонов
Один и тот же файл не должен попадать одновременно в два правила.
Проверьте:
sudo grep -Rni '/var/log/nginx' /etc/logrotate.conf /etc/logrotate.d/
Дублирование может вызвать ошибку:
duplicate log entry
Настройка владельца и группы
Проверьте:
sudo ls -l /var/log/nginx/
Стандартно журналы могут иметь:
www-data adm
или другое сочетание в зависимости от пакета.
В create укажите фактические значения.
su в logrotate
Для некоторых нестандартных каталогов требуется:
su www-data adm
Пример:
/var/log/nginx/custom/*.log {
su www-data adm
daily
rotate 14
compress
}
Не добавляйте su без необходимости и проверки прав каталога.
Права на каталог
sudo stat /var/log/nginx
Проверьте:
- владельца;
- группу;
- права;
- доступ процесса Nginx;
- доступ logrotate.
Проверка SELinux и AppArmor
На стандартной Ubuntu чаще используется AppArmor.
Если журналы перенесены в нестандартный каталог и Nginx не может открыть новый файл, проверьте системный журнал:
sudo journalctl -k -n 100 --no-pager
Также проверьте:
sudo journalctl -u nginx -n 100 --no-pager
Ротация access.log отдельно от error.log
Можно создать разные политики.
Пример для access log:
/var/log/nginx/*access.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /run/nginx.pid ]; then
kill -USR1 $(cat /run/nginx.pid)
fi
endscript
}
Пример для error log:
/var/log/nginx/*error.log {
weekly
rotate 8
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /run/nginx.pid ]; then
kill -USR1 $(cat /run/nginx.pid)
fi
endscript
}
Но разделять правила стоит только при реальной необходимости.
dateext
Для архивов с датой:
dateext
Пример имён:
access.log-20260726.gz
Дополнительно можно задать:
dateformat -%Y%m%d
Пример с dateext
daily
rotate 30
compress
delaycompress
dateext
dateformat -%Y%m%d
Не меняйте схему имён без учёта скриптов, которые читают старые журналы.
maxage
Можно удалять архивы старше определённого количества дней:
maxage 30
Пример:
daily
rotate 30
maxage 30
rotate и maxage работают совместно, но итоговое удаление зависит от фактических запусков logrotate.
Запрет ротации пустых файлов
notifempty
Пустой файл останется без создания пустого архива.
Сжатие через другой алгоритм
По умолчанию используется gzip.
Менять алгоритм обычно не требуется.
Совместимость стандартных инструментов и минимальная сложность важнее небольшой экономии места.
Проверка архивного журнала
Для .gz:
sudo zcat /var/log/nginx/access.log.2.gz |
head
Просмотр без распаковки:
sudo zless /var/log/nginx/access.log.2.gz
Поиск:
sudo zgrep ' 500 ' /var/log/nginx/access.log.*.gz |
tail
Поиск по текущим и архивным логам
Текущий файл:
sudo grep ' 404 ' /var/log/nginx/access.log |
tail
Архив без сжатия:
sudo grep ' 404 ' /var/log/nginx/access.log.1 |
tail
Сжатые архивы:
sudo zgrep ' 404 ' /var/log/nginx/access.log.*.gz |
tail
Ротация не заменяет централизованный сбор
Logrotate решает локальную задачу управления файлами.
Он не заменяет:
- Loki;
- Elasticsearch;
- Graylog;
- удалённый syslog;
- SIEM;
- резервное хранение журналов.
Если журналы нужны для аудита, отправляйте их на отдельный сервер до удаления локальных копий.
Не удаляйте активный лог вручную
Плохой вариант:
sudo rm /var/log/nginx/access.log
Nginx может продолжить писать в удалённый inode, а место не освободится до закрытия файлового дескриптора.
Проверьте удалённые открытые файлы:
sudo lsof +L1 |
grep nginx
Освобождение места после ручного удаления
Если лог был удалён, но процесс продолжает держать его открытым:
sudo kill -USR1 "$(cat /run/nginx.pid)"
После этого Nginx переоткроет журналы.
Перед сигналом проверьте PID и конфигурацию.
Не обнуляйте файлы без причины
Команда:
sudo truncate -s 0 /var/log/nginx/access.log
может временно освободить место, но нарушает нормальную историю журналов.
Используйте её только как аварийную меру, а затем исправьте ротацию.
Ошибка permission denied
Проверьте:
sudo ls -ld /var/log/nginx
sudo ls -l /var/log/nginx
Проверьте параметры:
create
su
Проверьте журнал службы:
sudo journalctl -u logrotate.service -n 100 --no-pager
Ошибка duplicate log entry
Найдите дубли:
sudo grep -Rni '/var/log/nginx' /etc/logrotate.conf /etc/logrotate.d/
Один файл должен обрабатываться одним правилом.
После ротации Nginx пишет в .1
Проверьте postrotate.
Вручную переоткройте:
sudo kill -USR1 "$(cat /run/nginx.pid)"
Проверьте:
sudo lsof -c nginx |
grep '/var/log/nginx'
Новый access.log не создаётся
Проверьте:
- директиву
create; - права каталога;
- пользователя Nginx;
- PID;
postrotate;- активную конфигурацию Nginx.
Создайте тестовый запрос:
curl -I http://127.0.0.1
Ротация не запускается ежедневно
Проверьте timer:
systemctl status logrotate.timer --no-pager
Проверьте календарь:
systemctl list-timers --all |
grep logrotate
Проверьте журнал:
sudo journalctl -u logrotate.service --since today --no-pager
Файл превысил maxsize, но не ротируется сразу
Logrotate не следит за файлами постоянно.
maxsize проверяется только во время запуска logrotate.
Если timer выполняется раз в сутки, файл может превысить лимит до следующего запуска.
Для более частой проверки потребуется отдельный timer, но это уже отдельная задача.
Архивы не сжимаются
При наличии:
delaycompress
самый свежий архив остаётся несжатым до следующей ротации.
Это нормальное поведение.
Проверка после следующего цикла
sudo ls -lah /var/log/nginx/
Ожидаемая структура:
access.log
access.log.1
access.log.2.gz
error.log
error.log.1
error.log.2.gz
Откат конфигурации
Найдите резервную копию:
sudo ls -1t /etc/logrotate.d/nginx.backup-* |
head
Восстановите:
sudo cp /etc/logrotate.d/nginx.backup-DATE /etc/logrotate.d/nginx
Замените DATE фактическим именем файла.
Проверьте:
sudo logrotate -d /etc/logrotate.d/nginx
Безопасный порядок настройки
- Проверить размер журналов.
- Проверить свободное место.
- Изучить текущее правило.
- Создать резервную копию.
- Настроить периодичность и хранение.
- Проверить владельца и группу.
- Проверить
postrotate. - Запустить debug mode.
- Выполнить принудительную ротацию.
- Создать тестовый HTTP-запрос.
- Убедиться, что запись идёт в новый лог.
- Проверить systemd timer.
Быстрый набор команд
Проверить размер:
sudo du -h /var/log/nginx/*
Проверить правило:
sudo cat /etc/logrotate.d/nginx
Тест без изменений:
sudo logrotate -d /etc/logrotate.d/nginx
Принудительная ротация:
sudo logrotate -f /etc/logrotate.d/nginx
Проверка новых файлов:
sudo ls -lah /var/log/nginx/
Проверка записи:
curl -I http://127.0.0.1
sudo tail -5 /var/log/nginx/access.log
Итог
После выполнения инструкции:
- проверена стандартная конфигурация logrotate;
- настроены периодичность и количество архивов;
- включено сжатие старых журналов;
- проверено переоткрытие файлов через
USR1; - выполнена безопасная принудительная ротация;
- проверена запись в новые журналы;
- рассмотрены отдельные журналы виртуальных хостов;
- разобраны типичные ошибки.
На этом базовую серию статей по Nginx можно считать завершённой.