Как освободить место в лог файле без перезагрузки приложения
Что проверяют
Понимаете ли вы, как Linux работает с открытыми файлами, и не создадите ли новую проблему, решая старую. Классическое продолжение: «Удалили лог, а место не освободилось. Почему?»
Как отвечать
Главное правило: файл, открытый процессом, после rm исчезает из каталога, но место занимает до закрытия дескриптора. Поэтому место освобождают не удалением, а обрезанием:
truncate -s 0 app.logили: > app.log: файл остаётся тем же, процесс пишет дальше, место освобождается сразу;- уже удалённый файл: найдите его через
lsof +L1и обрежьте через дескриптор процесса:: > /proc/<pid>/fd/<N>; - ротация без рестарта: в
logrotateестьcopytruncate, он копирует лог и обрезает оригинал. Второй путь:createи команда вpostrotate, после которой приложение само переоткроет файл, напримерnginx -s reopen; - journald и Docker:
journalctl --vacuum-size=500Mчистит журнал, у драйвераjson-fileзадаютсяmax-sizeиmax-fileвdaemon.json. В Kubernetes логи контейнеров ротирует kubelet.
Проговорите нюанс обрезки: если приложение открыло файл без O_APPEND, оно продолжит писать со старого смещения. Получится разреженный файл: ls покажет прежний размер, а du только реально записанные блоки.
Долгосрочное решение: писать логи в stdout и отправлять в Loki или ELK, а на диске держать только ротируемый буфер.
Где спотыкаются
Делают rm или gzip на активном логе. gzip создаёт архив и удаляет оригинал, но процесс продолжает писать в удалённый inode, и место уходит дальше, уже невидимо для du.
Шлют kill -USR1 любому процессу как «универсальную команду ротации». Сигнал что-то значит только для приложений, которые его обрабатывают, а для остальных действие по умолчанию это завершение процесса.
Не знают про окно в copytruncate: строки, записанные между копированием и обрезкой, теряются. Для аудиторских логов этот режим не годится.