Логи и их ротация: /var/log, rsyslog, logrotate

↑ Этап 1 · Фундамент: Linux, Bash, сети

Желательно~6 мин чтенияУровень: junior

Зачем это на собесе

Логи — главный источник диагностики; переполнение диска логами — классический инцидент. Нужны ротация и понимание пути логов.

Где лежат логи

ПутьЧто
/var/log/syslog (Debian) / /var/log/messages (RHEL)общие сообщения
/var/log/auth.log / /var/log/secureаутентификация, sudo, ssh
/var/log/kern.log, dmesgядро
/var/log/nginx/access.log, error.logвеб-сервер
/var/log/postgresql/БД
/var/log/journal/журнал systemd (бинарный)
/var/log/apt/, dpkg.logпакеты
/var/lib/docker/containers/<id>/<id>-json.logлоги контейнеров

syslog и rsyslog

Syslog — стандарт сообщений: facility (auth, kern, daemon, local0–7) и severity (0 emerg … 3 err, 4 warning, 6 info, 7 debug). rsyslog — демон: принимает сообщения (из /dev/log, по сети UDP/TCP 514), фильтрует и маршрутизирует по правилам.

# /etc/rsyslog.d/30-myapp.conf
if $programname == 'myapp' then /var/log/myapp/app.log
& stop
 
# отправка на центральный сервер по TCP
*.* @@logs.internal:514
logger -p local0.info -t myapp "deploy started"     # записать сообщение из скрипта

Современные дистрибутивы: журнал journald собирает stdout/stderr сервисов и syslog; rsyslog может читать из него (imjournal) и пересылать дальше.

Ротация логов: logrotate

Без ротации файлы растут бесконечно. logrotate запускается по cron/systemd timer, по политикам /etc/logrotate.d/*.

/var/log/myapp/*.log {
    daily                 # weekly, monthly или size 100M
    rotate 14             # хранить 14 архивов
    compress
    delaycompress         # сжимать со второго цикла (приложение ещё может писать в предыдущий)
    missingok
    notifempty
    create 0640 myapp myapp
    sharedscripts
    postrotate
        systemctl reload myapp >/dev/null 2>&1 || true     # переоткрыть файл логов
    endscript
}

Варианты обработки открытого файла:

  • postrotate с reload/HUP: приложение переоткрывает файл (nginx: nginx -s reopen или kill -USR1);
  • copytruncate: копирует и обнуляет файл, не требует сигнала, но возможна потеря строк между копированием и усечением.

Проверка: logrotate -d /etc/logrotate.d/myapp (dry-run), logrotate -f (принудительно). Состояние — /var/lib/logrotate/status.

Ротация journald

# /etc/systemd/journald.conf
Storage=persistent
SystemMaxUse=1G
MaxRetentionSec=14day
journalctl --disk-usage; sudo journalctl --vacuum-size=500M

Логи контейнеров

Драйвер json-file по умолчанию без лимита: безлимитный рост.

// /etc/docker/daemon.json
{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "5" } }
# docker-compose
logging:
  driver: json-file
  options: { max-size: "50m", max-file: "5" }

Другие драйверы: local (компактный с ротацией), journald, fluentd, syslog, gelf. Приложение в контейнере пишет в stdout/stderr (12-factor), а сбор — на уровне платформы.

Рекомендации по логированию

  • структурированные логи (JSON) — удобно искать и агрегировать;
  • уровни (DEBUG/INFO/WARN/ERROR), в проде по умолчанию INFO;
  • корреляция: trace_id, request_id, пользователь (не PII);
  • не логировать пароли, токены, персональные данные;
  • время в UTC, ISO 8601;
  • централизованный сбор (Loki, ELK, ClickHouse) — логи не теряются при смерти хоста;
  • мониторинг объёма и ошибок, алерты на всплески ERROR;
  • хранить в соответствии с политикой (ретенция, закон).

Диагностика

tail -f /var/log/myapp/app.log
grep -c ERROR /var/log/myapp/app.log
journalctl -u myapp -p err --since today
du -sh /var/log/* | sort -h | tail
ls -lh /var/log | sort -k5 -h | tail
lsof +L1     # удалённые логи, которые процесс держит открытыми

Типичная проблема: логи удалили (rm), но процесс держит дескриптор — место не освободилось; правильно ротировать (reopen) или обнулять (: > file, truncate -s 0).

Вопросы с ответами