open atlas
↑ К треку
Linux: операционная система LIN · 10 · 02

Постоянный журнал и ротация логов

По умолчанию journald volatile: логи исчезают при перезагрузке, пока не задан Storage=persistent в journald.conf. SystemMaxUse ограничивает диск. journalctl --vacuum-size/--vacuum-time чистит старые данные. logrotate управляет текстовыми логами в /var/log.

LIN Middle ◷ 22 min
Уровень
ОсновыJuniorMiddleSenior

Сервис падает в 3 ночи, дежурный перезагружает сервер, а утром логи исчезли. Не сротированы — исчезли совсем. Журнал был volatile: он жил в /run/log/journal, который является tmpfs и стирается при каждой перезагрузке. Это поведение по умолчанию на многих установках Debian и Ubuntu. Исправление — одна строка конфига, но если не знать умолчание, при каждом инциденте будешь терять доказательства. Вторая ловушка — противоположная: журнал сделан постоянным, лимит не задан, и через шесть месяцев диск переполнен, потому что SystemMaxUse так и не был настроен. Оба сценария предотвратимы, когда понимаешь разницу volatile/persistent и умеешь задавать размер и чистить журнал.

Цель

После этого урока ты сможешь различать volatile и persistent хранилище журнала, включать постоянность через Storage=persistent, задавать ограничения размера через SystemMaxUse, обрезать данные журнала командами --vacuum-size и --vacuum-time, а также настраивать logrotate для текстовых логов, которые приложения пишут в /var/log.

1

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.

2

Включить постоянное хранилище.

Одна строка в 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

После включения постоянности логи следующей и всех последующих загрузок переживают перезагрузки. Логи до изменения ретроактивно не сохраняются.

3

Ограничение размера журнала через 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  ← в пределах лимита 500M

journald соблюдает лимит, ротируя и удаляя самые старые архивные файлы журнала. Команды очистки вручную не нужны — соблюдение непрерывное.

4

Ручная очистка: обрезать данные журнала по требованию.

Когда нужно немедленно освободить место (например, после шторма логов), используй --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-usage

Vacuum удаляет только архивные (сротированные) журналы, никогда — активный. Безопасно запускать на живой системе. Типичный паттерн: запускать --vacuum-time=30d еженедельно через systemd timer или cron.

5

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-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.