Выберите продукт

Logrotate: права, copytruncate и postrotate без сюрпризов

Разбираем logrotate на практике: почему ротация ломается из‑за прав на каталоги, как правильно настроить create и su, когда оправдан copytruncate и как писать postrotate с sharedscripts без лишних reload.
Logrotate: права, copytruncate и postrotate без сюрпризов

Зачем вообще разбираться в нюансах logrotate

Ротация логов в Linux кажется простой задачей: «переименовал файл, сжал, удалил старое». Но на проде именно logrotate часто становится источником тихих проблем: приложение перестаёт писать в лог (пишет в удалённый inode), ротация не срабатывает из-за прав доступа, postrotate дергает сервис слишком часто, а copytruncate незаметно теряет строки в моменты пиков.

Ниже разберём самые частые грабли вокруг logrotate: права/владельцы, директивы create и su, режим copytruncate, хуки postrotate, а также практичные мелочи вроде missingok, notifempty, rotate, compress и sharedscripts.

Как работает logrotate: коротко о механике

Обычно logrotate запускается по расписанию (cron или systemd timer) и читает конфиги из /etc/logrotate.conf и /etc/logrotate.d/. Для каждого правила он решает, пора ли «крутить» лог (по времени или размеру), и выполняет шаги:

  • проверяет условия (существует ли файл, не пустой ли, не ротировался ли недавно и т. п.);
  • делает ротацию: переименовывает (или копирует) текущий файл в .1, сдвигает старые .2, .3 и т. д. согласно rotate;
  • создаёт новый файл (директива create) или оставляет приложению самому создать новый;
  • при необходимости сжимает (compress) и выполняет скрипты (postrotate, prerotate и т. п.).

Ключевой момент: большинство проблем происходит на стыке «кто владелец файла» и «кто выполняет действия logrotate».

Если логи у вас активно анализируются (например, для отчетов по трафику и аномалиям), полезно держать ротацию и права в порядке: иначе парсеры начинают «видеть дырки» или упираются в доступы. По теме анализа логов может пригодиться материал про связку goaccess, logrotate и алерты по логам.

Проверка прав каталогов и файла лога командой namei

Типовые ошибки permissions: почему “Permission denied” и “skipping”

logrotate чаще всего запускается от root. Кажется, что root может всё — но это не всегда так: безопасность в logrotate устроена жёстко, и он может отказать в ротации, если видит небезопасные права у каталога или файла. Это сделано, чтобы исключить подмену файлов/линков (класс атак через world-writable каталоги).

Самые частые симптомы:

  • в debug видно «skipping … because parent directory has insecure permissions»;
  • ошибка «Permission denied» при попытке создать новый файл;
  • после ротации приложение не пишет в новый лог (файл создан с неправильными owner/group/mode);
  • ротация отрабатывает, но postrotate не выполняется из-за раннего выхода по ошибке.

Проверьте права: файл и каталоги по пути

Даже если сам лог-файл нормальный, проблемным может быть любой каталог на пути. Проверка, которую удобно делать первой:

namei -l /var/log/nginx/access.log

Команда покажет права на каждый каталог и на файл. Опасные варианты:

  • каталог логов или его родитель имеет права 777 или просто доступен на запись всем (o+w);
  • лог-файл принадлежит не тому пользователю, а logrotate пытается создать новый с create без прав;
  • владелец файла — root, а приложение пишет от непривилегированного пользователя (или наоборот).

Диагностика: прогон в debug и принудительный запуск

Чтобы понять, что logrotate собирается делать, полезны два режима:

logrotate -d /etc/logrotate.conf

Это «dry-run»: показывает план действий, но ничего не меняет.

logrotate -vf /etc/logrotate.conf

Это принудительный запуск (-f) с подробным выводом (-v). На проде используйте аккуратно: можно неожиданно дернуть postrotate и reload/рестарты.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

create: кто создаёт новый лог и с какими правами

Директива create управляет созданием нового пустого файла после ротации (когда ротация делается переименованием). Типичный вид:

/var/log/myapp/*.log {
  daily
  rotate 14
  missingok
  notifempty
  compress
  create 0640 myapp adm
}

Важно понимать: если вы используете create, именно logrotate создаст новый файл и выставит права/владельца. Если create не указана, то после переименования «старого» файла приложение должно само создать новый (или продолжит писать в старый inode, если вы не сделали reload/reopen логов).

Практическая рекомендация: для большинства демонов и веб-сервисов create удобен, но только если вы точно знаете, под каким пользователем процесс пишет в лог. Ошибка в owner/group обычно выглядит как «лог замолчал».

su directive: лечим проблемы с правами без лишних привилегий

Директива su указывает, под каким пользователем и группой logrotate должен выполнять операции ротации внутри конкретного блока. Это критично, когда логи лежат в каталоге сервиса (например, в /srv) и вы не хотите расширять права каталога ради root-задачи.

Пример для приложения, которое пишет в каталог, принадлежащий пользователю myapp:

/srv/myapp/log/*.log {
  daily
  rotate 7
  missingok
  notifempty
  compress
  su myapp myapp
  create 0640 myapp myapp
}

Чем su полезна на практике:

  • не нужно делать каталог логов «широким» по правам;
  • меньше риска, что create создаст файл с неправильным owner/group;
  • логичнее с точки зрения безопасности: ротация происходит с правами сервиса, а не с максимальными привилегиями.

Нюанс: в разных дистрибутивах и версиях logrotate контекст исполнения скриптов и файловых операций может отличаться. После добавления su обязательно проверьте реальное поведение в вашей системе через logrotate -d и тестовую ротацию.

copytruncate: когда выручает и чем опасен

copytruncate — популярная директива, когда сервис нельзя или неудобно заставлять переоткрывать лог-файл. Она работает так: logrotate копирует текущий лог в ротированный файл и затем обнуляет исходный файл (truncate), не меняя inode. Процесс, который держит открытый дескриптор, продолжит писать в тот же файл — просто после обнуления.

Пример:

/var/log/legacy-app.log {
  size 200M
  rotate 10
  missingok
  notifempty
  compress
  copytruncate
}

Главный минус copytruncate — возможная потеря строк

Между «копированием» и «truncate» есть окно времени. Если в этот момент приложение активно пишет, часть строк может:

  • попасть в ротированный файл, но не попасть в текущий (или наоборот);
  • попасть в текущий уже после копирования и исчезнуть после truncate.

На низкой нагрузке это почти незаметно. На высоких RPS/лог-флуде — вполне реально.

Когда copytruncate оправдан

  • старое ПО, которое не умеет переоткрывать лог по сигналу/reload;
  • нет возможности делать reload/рестарт (жёсткий SLA, критичные соединения);
  • логирование не является источником аудита/биллинга, и потеря небольшой доли строк допустима.

Когда лучше не использовать copytruncate

  • аудит/безопасность/финансы: нужна полнота событий;
  • очень высокая интенсивность записи в лог;
  • приложение умеет reopen/reload логов (тогда лучше классическая схема с переименованием + reload).

postrotate: что выполнять после ротации и как не «уронить» сервис

postrotate — блок команд, который logrotate выполняет после успешной ротации. Обычно здесь делают reload сервиса, чтобы он переоткрыл файлы логов и начал писать в новый файл (особенно когда не используется copytruncate).

Классический пример (перезагрузка без полноценного рестарта):

/var/log/nginx/*.log {
  daily
  rotate 14
  missingok
  notifempty
  compress
  delaycompress
  create 0640 www-data adm
  sharedscripts
  postrotate
    systemctl reload nginx
  endscript
}

sharedscripts: чтобы postrotate не выполнялся N раз

Если в блоке указано несколько файлов (например, /var/log/nginx/*.log), то по умолчанию скрипты могут выполниться для каждого файла отдельно. Для nginx это означает несколько reload подряд. Директива sharedscripts говорит: «выполни скрипты один раз на весь блок».

Практически всегда для веб-серверов и сервисов с набором логов стоит включать sharedscripts, чтобы избежать лишних reload/дергания systemd.

Делайте postrotate «мягким»

Ошибки в postrotate — частая причина «странной» ротации. Рабочие правила:

  • используйте reload вместо restart, если сервис это поддерживает;
  • не пишите интерактивные команды;
  • не логируйте вывод скрипта в тот же каталог/файл, который крутите, чтобы случайно не устроить рекурсию;
  • проверяйте окружение: в контейнерах systemctl может отсутствовать, тогда нужен другой механизм reopen.
FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

missingok и notifempty: чтобы ротация не мешала жизни

Эти две директивы часто стоит включать по умолчанию для «необязательных» логов.

  • missingok — не считать ошибкой отсутствие файла. Полезно, когда лог создаётся не всегда (например, только при включённом debug) или сервис иногда выключен.
  • notifempty — не ротировать пустые файлы. Это снижает «мусор» из нулевых архивов и лишних действий.

Комбинация missingok notifempty обычно делает поведение logrotate более предсказуемым.

rotate, compress и delaycompress: хранение и нагрузка

Базовые директивы хранения:

  • rotate — сколько архивов хранить (например, rotate 14 = две недели при daily);
  • compress — сжимать ротированные логи;
  • delaycompress — не сжимать самый свежий .1 до следующей ротации.

delaycompress полезен, когда какие-то процессы ещё могут читать свежий ротированный лог (сборщики метрик, парсеры, диагностика), либо если вы делаете reload, но опасаетесь гонок чтения.

Также помните про CPU: сжатие больших логов в пиковые часы может давать заметный всплеск нагрузки. В таких случаях лучше ротировать по размеру, либо подбирать частоту так, чтобы компрессия попадала в «тихие» окна.

Практический шаблон: безопасная ротация без copytruncate

Если сервис умеет перечитывать или переоткрывать логи по reload (или по сигналу), обычно лучше избегать copytruncate и использовать «классическую» схему: переименование + create + postrotate reload.

/var/log/myservice/*.log {
  daily
  rotate 14
  missingok
  notifempty
  compress
  delaycompress
  su myservice myservice
  create 0640 myservice myservice
  sharedscripts
  postrotate
    systemctl reload myservice
  endscript
}

Что здесь решает проблемы заранее:

  • su и create фиксируют permissions и владельцев;
  • sharedscripts предотвращает многократный reload;
  • missingok и notifempty убирают ложные ошибки и пустые ротации;
  • compress экономит место, а delaycompress снижает риск конфликтов со свежим архивом.

Если без copytruncate никак: минимизируем риски

Когда вы вынуждены использовать copytruncate, разумно хотя бы:

  • ротировать по размеру, чтобы операция копирования была быстрее и окно потерь — меньше;
  • держать разумное число rotate, достаточное для расследований;
  • включить compress, чтобы не съесть диск;
  • учесть буферизацию: если приложение пишет большими буферами и редко flush, в момент truncate можно потерять не только строки, но и куски буфера.

Пример более «бережной» конфигурации:

/var/log/legacy-app.log {
  size 100M
  rotate 20
  missingok
  notifempty
  compress
  copytruncate
}

Чек-лист: что проверить, если ротация не работает или работает странно

  1. План действий: logrotate -d /etc/logrotate.conf.

  2. Тест с подробным выводом: logrotate -vf /etc/logrotate.conf (осторожно с postrotate).

  3. Права каталогов по пути: namei -l. Ищите world-writable и неожиданных владельцев.

  4. Корректность create: owner/group должны совпадать с тем, кто пишет в лог.

  5. Если есть проблемы с доступом и «insecure permissions» — добавьте su в блок.

  6. Если сервис после ротации пишет «в никуда» — вам нужен postrotate (reload/reopen), либо copytruncate как компромисс.

  7. Если postrotate выполняется слишком много раз — включите sharedscripts.

  8. Если плодятся пустые архивы — включите notifempty.

  9. Если иногда файла нет — включите missingok.

Итог

В logrotate важны не столько «daily и rotate», сколько детали: кому принадлежат файлы, под кем выполняются операции (su), кто создаёт новый лог (create), как сервис переоткрывает дескрипторы (postrotate), и не прячете ли вы проблемы под copytruncate ценой потерь событий.

Если вы один раз аккуратно настроите права и хук переоткрытия логов, logrotate станет «скучной» системой — а это лучший комплимент для продовой инфраструктуры, будь то сервер на VDS или типовой веб-проект на виртуальном хостинге.

Контроль места на диске и архивов логов после ротации

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: APT repository does not have a Release file — как исправить ошибку OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: APT repository does not have a Release file — как исправить ошибку

Ошибка APT repository does not have a Release file в Debian и Ubuntu обычно связана с неподдерживаемым репозиторием, неверным code ...
Debian/Ubuntu: SSH зависает на Connecting to — как найти и убрать задержку входа OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: SSH зависает на Connecting to — как найти и убрать задержку входа

Если SSH в Debian или Ubuntu зависает на этапе Connecting to, долго показывает banner или тормозит уже после ввода пароля, причина ...
Debian/Ubuntu: конфликт systemd-resolved DNSStubListener на 127.0.0.53 с dnsmasq, Unbound и BIND OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: конфликт systemd-resolved DNSStubListener на 127.0.0.53 с dnsmasq, Unbound и BIND

Если локальный DNS в Debian или Ubuntu не стартует с ошибкой address already in use, причина часто в systemd-resolved и DNSStubLis ...