Почему не освобождается место после удаления логов в Linux?

Ответ

Основная причина — удалённый файл всё ещё удерживается открытым дескриптором работающего процесса. В Linux место на диске освобождается только после того, как все жёсткие ссылки на файл удалены и все открытые дескрипторы закрыты.

Типичные сценарии и решения:

  1. Процесс держит файл открытым. Часто случается с демонами (nginx, app-server), которые пишут логи.

    • Проверка: lsof +L1 или lsof | grep deleted покажет процессы и размер удалённых, но открытых файлов.
    • Решение: Отправить процессу сигнал для переоткрытия логов (например, systemctl reload nginx или kill -HUP <PID>). Полный перезапуст (restart) также решит проблему.
  2. Использование logrotate без copytruncate. По умолчанию logrotate создаёт копию лога и просит процесс переоткрыть файл. Если процесс этого не делает (не поддерживает сигнал), старый дескриптор остаётся.

    • Решение: В конфигурации logrotate для проблемного сервиса используйте директиву copytruncate. Она копирует файл, а затем обрезает оригинал до нуля, не требуя от процесса переоткрытия.
      /var/log/myapp.log {
      daily
      rotate 7
      copytruncate  # Ключевая директива
      missingok
      }
  3. Монтирование в пространство имён контейнера. Файл может быть удалён внутри контейнера, но оставаться открытым на хосте.

Порядок диагностики:

  1. df -h — показывает «занятое» место, включая файлы с открытыми дескрипторами.
  2. du -sh /var/log/ — показывает реальный размер файлов в директории. Если df показывает много занятого, а du — мало, это явный признак проблемы.
  3. lsof | grep deleted — найти виновника.
  4. Принять меры (перезагрузка, copytruncate, очистка диска от других файлов).

Ответ 18+ 🔞

А, ну это классика, ёпта! Ситуация, от которой у любого админа волосы дыбом встают: вроде файлы удалил, а место на диске как будто испарилось. Овердохуища занято, а куда — хрен поймёшь.

Короче, вся соль в том, что в Линуксе место освобождается только тогда, когда на файл вообще никто не ссылается. То есть все жёсткие ссылки удалены и все открытые дескрипторы закрыты. А если какой-то процесс этот файл не отпустил, то он физически на диске остаётся, хоть ты его из каталога и выкинул. Манда с ушами, а не ситуация.

Где обычно искать эту хитрожопую проблему и как её решать:

  1. Процесс-невидимка. Чаще всего это какой-нибудь демон, который логи пишет, типа nginx или твоего app-server'а. Ты лог-файл удалил, а он своё держит за хвост старым дескриптором.

    • Как найти виновника: Команда lsof +L1 или lsof | grep deleted тебе всё покажет — кто держит, PID и какой размер у этого «призрака».
    • Что делать: Нужно заставить процесс отпустить старый файл и открыть новый. Часто хватает вежливого сигнала на переоткрытие логов: systemctl reload nginx или kill -HUP <PID>. Ну а если не понимает по-хорошему — полный перезапуск (restart) всегда работает, хоть это и тупой метод.
  2. Логротейт подвел. Вот тут, бля, тонкий момент. По умолчанию logrotate делает копию лога, удаляет оригинал и просит процесс переоткрыть файл по сигналу. А если процесс — пидарас шерстяной и сигналы не ловит? Он так и будет писать в тот же удалённый файл своим старым дескриптором.

    • Решение — костыль, но рабочий: В конфиге logrotate для проблемного сервиса пропиши директиву copytruncate. Она работает по-другому: сначала копирует файл, а потом обрезает оригинал до нуля. Процессу даже не нужно переоткрывать файл, он просто продолжает писать в тот же дескриптор, но файл уже пустой. Гениально и просто, как валенок.
      /var/log/myapp.log {
      daily
      rotate 7
      copytruncate  # Вот эта волшебная палочка-выручалочка
      missingok
      }
  3. Контейнеры, ёб твою мать. Отдельная песня. Файл могли удалить внутри контейнера, а на хосте он всё ещё висит открытым. Тут уже надо смотреть и там, и там.

Так, а теперь по шагам, как не охуеть от неожиданности и найти, куда делось место:

  1. df -h — показывает общую картину, включая эти самые «призрачные» файлы. Цифра будет пугать.
  2. du -sh /var/log/ — а вот это показывает реальный размер того, что лежит в папке сейчас. Если df кричит, что места нет, а du показывает, что всё чисто — поздравляю, ты нашёл проблему. Сам от себя охуел, да?
  3. lsof | grep deleted — финальный аккорд. Эта команда тычет пальцем прямо в морду процессу-вредителю. Смотри PID и размер.
  4. Дальше уже действуй по обстановке: перезагрузи сервис, настрой copytruncate или просто почисти другие файлы, если срочно нужно место. Главное — теперь-то ты знаешь, в чём дело.