Постоянный журнал и ротация логов
По умолчанию journald volatile: логи исчезают при перезагрузке, пока не задан Storage=persistent в journald.conf. SystemMaxUse ограничивает диск. journalctl --vacuum-size/--vacuum-time чистит старые данные. logrotate управляет текстовыми логами в /var/log.
Сервис падает в 3 ночи, дежурный перезагружает сервер, а утром логи исчезли. Не сротированы — исчезли совсем. Журнал был volatile: он жил в /run/log/journal, который является tmpfs и стирается при каждой перезагрузке. Это поведение по умолчанию на многих установках Debian и Ubuntu. Исправление — одна строка конфига, но если не знать умолчание, при каждом инциденте будешь терять доказательства. Вторая ловушка — противоположная: журнал сделан постоянным, лимит не задан, и через шесть месяцев диск переполнен, потому что SystemMaxUse так и не был настроен. Оба сценария предотвратимы, когда понимаешь разницу volatile/persistent и умеешь задавать размер и чистить журнал.
После этого урока ты сможешь различать volatile и persistent хранилище журнала, включать постоянность через Storage=persistent, задавать ограничения размера через SystemMaxUse, обрезать данные журнала командами --vacuum-size и --vacuum-time, а также настраивать logrotate для текстовых логов, которые приложения пишут в /var/log.
Volatile vs persistent: где живёт журнал?
journald хранит записи в одном из двух мест в зависимости от конфигурации:
# Проверить, где сейчас живёт журнал:
ls /run/log/journal/ # volatile — теряется при перезагрузке (tmpfs)
ls /var/log/journal/ # persistent — переживает перезагрузку
# Проверить использование диска:
journalctl --disk-usage
# Archived Journals: 0 B
# Active Journals: 48.0 M
# На системе только с volatile-хранилищем:
# /var/log/journal/ НЕ существует
# Все данные в /run/log/journal/ (tmpfs, теряется при перезагрузке)
# Проверить текущую настройку Storage:
grep -i storage /etc/systemd/journald.conf 2>/dev/null || \
grep -i storage /etc/systemd/journald.conf.d/*.conf 2>/dev/null || \
echo "Storage= не задан — умолчание auto"Умолчание Storage=auto означает: использовать persistent, если /var/log/journal/ уже существует, иначе — volatile. На свежей установке Ubuntu /var/log/journal/ обычно не существует, поэтому по умолчанию ты в режиме volatile.
Включить постоянное хранилище.
Одна строка в journald.conf и создание директории:
# Создать конфигурационный drop-in:
sudo mkdir -p /etc/systemd/journald.conf.d/
sudo tee /etc/systemd/journald.conf.d/persistence.conf <<'EOF'
[Journal]
Storage=persistent
EOF
# Создать директорию постоянного хранилища:
sudo mkdir -p /var/log/journal
# Применить изменение (перезагрузка не нужна):
sudo systemctl restart systemd-journald
# Проверить:
journalctl --disk-usage
# Archived Journals: 0 B
# Active Journals: 52.0 M ← теперь на диске в /var/log/journal/
ls /var/log/journal/
# <machine-id>/ ← одна директория на machine IDПосле включения постоянности логи следующей и всех последующих загрузок переживают перезагрузки. Логи до изменения ретроактивно не сохраняются.
Ограничение размера журнала через SystemMaxUse.
Без ограничения размера постоянный журнал будет расти, пока не заполнит диск. У journald есть встроенные умолчания (10% файловой системы или 4 ГБ, что меньше), но на небольшом VPS это умолчание всё равно может съесть критическое место.
# Задать явные ограничения размера в drop-in:
sudo tee /etc/systemd/journald.conf.d/size.conf <<'EOF'
[Journal]
SystemMaxUse=500M
SystemKeepFree=200M
RuntimeMaxUse=100M
EOF
# SystemMaxUse — максимум диска для журнала
# SystemKeepFree — всегда держать столько свободным на разделе
# RuntimeMaxUse — ограничение для volatile-журнала (/run)
sudo systemctl restart systemd-journald
# Проверить использование после перезапуска:
journalctl --disk-usage
# Archived Journals: 320.1 M
# Active Journals: 48.0 M
# Total: 368.1 M ← в пределах лимита 500Mjournald соблюдает лимит, ротируя и удаляя самые старые архивные файлы журнала. Команды очистки вручную не нужны — соблюдение непрерывное.
Ручная очистка: обрезать данные журнала по требованию.
Когда нужно немедленно освободить место (например, после шторма логов), используй --vacuum-size или --vacuum-time:
# Удалить архивные журналы до суммарного размера 200M:
sudo journalctl --vacuum-size=200M
# Vacuuming done, freed 148.3M of archived journals
# Удалить журналы старше 2 недель:
sudo journalctl --vacuum-time=2weeks
# Удалить журналы старше 30 дней:
sudo journalctl --vacuum-time=30d
# Комбинировать (применяется более строгое):
sudo journalctl --vacuum-size=500M --vacuum-time=30d
# Проверить место после очистки:
journalctl --disk-usageVacuum удаляет только архивные (сротированные) журналы, никогда — активный. Безопасно запускать на живой системе. Типичный паттерн: запускать --vacuum-time=30d еженедельно через systemd timer или cron.
logrotate для текстовых логов в /var/log.
Не всё идёт через journald. Приложения вроде nginx, PostgreSQL и многие унаследованные демоны всё ещё пишут в файлы под /var/log. Ими управляет logrotate.
# logrotate управляется через /etc/logrotate.conf и /etc/logrotate.d/:
cat /etc/logrotate.d/nginx
# /var/log/nginx/*.log {
# daily
# missingok
# rotate 14
# compress
# delaycompress
# notifempty
# create 0640 www-data adm
# sharedscripts
# postrotate
# /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
# endscript
# }
# Ключевые директивы:
# daily/weekly/monthly — частота ротации
# rotate 14 — хранить 14 сротированных файлов, затем удалять
# compress — gzip сротированных файлов (экономит ~90% места)
# delaycompress — не сжимать самый последний сротированный файл
# (nginx может ещё писать в него)
# postrotate/endscript — выполнить этот блок после ротации
# (посылает USR1 nginx для переоткрытия лог-файлов)
# Тестировать logrotate без реального выполнения (dry run):
sudo logrotate --debug /etc/logrotate.d/nginx
# Принудительно выполнить ротацию немедленно:
sudo logrotate --force /etc/logrotate.d/nginxБлок postrotate критически важен: приложения, держащие дескриптор открытым, продолжают писать в старый (переименованный) файл даже после того, как logrotate его переместил. Отправка USR1 (или перезагрузка сервиса) говорит приложению закрыть и переоткрыть дескриптор лог-файла — и оно начинает писать в новый пустой файл.
Освобождение места на диске после переполнения /var/log/journal из-за бесконтрольного логгера.
Приходит алерт о заполненном диске. df -h показывает / на 99%. Расследование:
# Найти, что потребляет место:
du -sh /var/log/journal/
# 4.2G /var/log/journal/
# Проверить разбивку:
journalctl --disk-usage
# Archived Journals: 3.8G
# Active Journals: 412.0M
# Total: 4.2G
# Сервис, вызвавший шторм (кто больше всего логировал за последние сутки):
journalctl --since "24 hours ago" | awk '{print $5}' | sort | uniq -c | sort -rn | head
# 48291 myapp[12345]:
# 3201 kernel:
# 812 sshd[...]:
# myapp залогировал 48к строк за 24ч — скорее всего, отладочное логирование в проде
# Немедленное облегчение: vacuum до 500M:
sudo journalctl --vacuum-size=500M
# Vacuuming done, freed 3.7G of archived journals
# Предотвратить повторение: задать лимит:
sudo tee /etc/systemd/journald.conf.d/size.conf <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=500M
EOF
sudo systemctl restart systemd-journald
# Устранить первопричину: отключить debug-логирование в конфиге myapp▸Частая ошибка
Забытый delaycompress в logrotate ломает приложения, держащие дескрипторы открытыми. Если сразу сжать последний сротированный файл, а приложение всё ещё пишет в него (через открытый дескриптор переименованного файла), сжатый результат может быть повреждён. delaycompress оставляет последний сротированный файл несжатым на один цикл, давая приложению время переоткрыть дескриптор. Сигнал в postrotate — дополнительная страховка: сигнал говорит приложению переоткрыть файл немедленно, а не ждать естественного закрытия дескриптора.
Коллега говорит: 'Я задал Storage=persistent, и теперь журнал растёт бесконтрольно — через 3 месяца он 8 ГБ.' Что он забыл и как немедленно исправить?
journald по умолчанию использует volatile-хранилище (/run/log/journal, стирается при перезагрузке), если не существует /var/log/journal/ или явно не задано Storage=persistent. Включение постоянности требует одного конфигурационного drop-in и systemctl restart systemd-journald. SystemMaxUse ограничивает, сколько диска может занять журнал — без него постоянный журнал растёт до заполнения диска. journalctl --vacuum-size и --vacuum-time обрезают архивные журналы по требованию, не трогая активный. Для текстовых логов приложений в /var/log logrotate выполняет ротацию, сжатие и отправку сигнала postrotate, чтобы приложения переоткрыли файловые дескрипторы. Два инструмента независимы: journald управляет своим бинарным хранилищем; logrotate — файлами /var/log/*.log.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.