🗂️
Хостинг

logrotate: как не дать логам заполнить диск

08.11.2026
← Все статьи

Чаще всего диск сервера «тихо» заполняют именно логи. Приложение записывает каждую ошибку, веб-сервер — каждый запрос, система — каждое событие, и если эти файлы никто не чистит, за несколько месяцев они вырастают до гигабайтов. Когда диск заполнен на 100 процентов, база данных перестаёт писать, сессии не сохраняются, а сайт начинает отдавать ошибки. Стандартное решение в Linux — утилита logrotate: она по расписанию ротирует логи, сжимает старые и удаляет всё, что сверх заданного количества.

Находим, что занимает диск

Прежде чем что-то настраивать, нужно понять, какие именно логи большие. Сначала посмотрите общее состояние диска, затем самые крупные каталоги и файлы в /var/log. Обычно виноваты один-два файла: лог ошибок приложения или access-лог веб-сервера.

df -h /
sudo du -sh /var/log/* 2>/dev/null | sort -h | tail -10
journalctl --disk-usage

Если /var/log небольшой, а диск всё равно забит, проверьте каталог приложения. storage/logs в Laravel, wp-content/debug.log в WordPress или логи собственных скриптов часто остаются вне стандартной ротации, потому что система о них просто не знает.

Пример: лог ошибок на 4 ГБ на сайте школы

Сайт частной школы в Самарканде misol.uz, написанный на Laravel, однажды перестал сохранять оценки учеников. Выяснилось, что приложение несколько месяцев на каждом запросе писало одно и то же предупреждение, и laravel.log вырос до 4 ГБ, съев всё свободное место. Очистка файла помогла временно, но настоящее исправление состояло из двух частей: источник предупреждения исправили в коде и добавили правило logrotate. После этого лог больше не превышал нескольких десятков мегабайт.

Как работает logrotate

Общие настройки лежат в /etc/logrotate.conf, а правила для отдельных сервисов — в каталоге /etc/logrotate.d/. В большинстве дистрибутивов logrotate запускается раз в сутки через таймер systemd или cron. Каждое правило задаёт, к каким файлам оно относится, как часто ротировать, сколько старых копий хранить и что делать после ротации. Например, daily вместе с rotate 14 означает «храни логи за последние 14 дней, более старые удаляй».

Правило для логов приложения

Создайте для приложения отдельный файл, например /etc/logrotate.d/misol. Правило ниже ротирует логи ежедневно, хранит 14 копий и сжимает их gzip. delaycompress оставляет самую свежую копию несжатой на сутки, чтобы не повредить файл, в который ещё может идти запись.

/var/www/misol/storage/logs/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

Директива copytruncate копирует файл, а затем обрезает оригинал до нуля. Это удобно для приложений, которые держат лог открытым и не умеют переоткрывать его по сигналу. Минус в том, что строки, записанные в короткий промежуток между копированием и обрезкой, могут потеряться. Если программа умеет переоткрывать лог, надёжнее связка create и postrotate.

Логи Nginx и postrotate

Пакет Nginx обычно приходит со своим правилом, но разобраться в нём полезно. Здесь старый файл переименовывается, новый создаётся с нужными правами, а Nginx получает сигнал USR1. По этому сигналу он переоткрывает лог-файлы и пишет уже в новые, перезапуск сервиса не нужен.

/var/log/nginx/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}

Без sharedscripts блок postrotate выполняется для каждого файла отдельно, а с ним — один раз после ротации всех файлов. На серверах с большим количеством доменов это избавляет от лишних сигналов.

Проверяем правило

Не стоит сразу доверять новому правилу. Параметр -d показывает, что будет сделано, ничего не меняя, а -f принудительно выполняет ротацию независимо от расписания. В каталоге должны появиться файлы с окончанием .1, а позже — .gz.

sudo logrotate -d /etc/logrotate.d/misol
sudo logrotate -f /etc/logrotate.d/misol
ls -lh /var/www/misol/storage/logs/

Журнал systemd и удалённые, но открытые файлы

Если journalctl --disk-usage показывает большой объём, журнал тоже нужно ограничить: разово очистить и задать постоянный предел.

sudo journalctl --vacuum-size=500M

# /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M

sudo systemctl restart systemd-journald

Иногда диск не освобождается даже после удаления лога через rm. Причина в том, что процесс, который в него писал, всё ещё держит файл открытым, и место вернётся только после остановки процесса. Такие файлы показывает команда ниже, а решение — перезапуск соответствующего сервиса. Поэтому активный лог лучше не удалять, а обнулять командой truncate -s 0.

sudo lsof +L1 | grep -i log

Свой logrotate на shared-хостинге

На shared-хостинге системные логи и логи веб-сервера ведёт провайдер, но собственные логи приложения занимают место в вашей квоте. Даже без root logrotate можно запускать от обычного пользователя: нужен свой конфигурационный файл и свой файл состояния (-s). Команду ставят в ежедневное расписание через задания cron в панели ISPmanager. Подставьте пути своего аккаунта и проверьте расположение программы командой which logrotate.

# ~/logrotate.conf
/home/user/www/misol.uz/storage/logs/*.log {
    weekly
    rotate 8
    compress
    missingok
    notifempty
    copytruncate
}

# cron: каждый день в 03:30
30 3 * * * /usr/sbin/logrotate -s $HOME/.logrotate.state $HOME/logrotate.conf

Если такой команды на хостинге нет или квота регулярно заканчивается, можно обратиться в техподдержку sayt.uz и вместе разобрать логи и расход диска. Главное — не только чистить лог, но и найти повторяющуюся ошибку, из-за которой он растёт: иначе ротация лишь скрывает проблему.

Похожие статьи

🤖 Python-бот 24/7: запуск через systemd и PM2 🧠 Нехватка памяти (OOM): почему завершаются процессы PHP и Python 🧠 «Allowed memory size exhausted»: ошибка памяти PHP и как её правильно решить 🚀 Полностраничный кеш: когда он полезен, а когда мешает
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English