На Linux-сервере можно удалить большой журнал через
rm, но df -h по-прежнему будет показывать заполненную файловую систему.rm /var/log/app/application.log
df -h /var
rm удаляет запись о файле из каталога и уменьшает количество жёстких ссылок на inode. Но если удалённый файл всё ещё открыт процессом, занятые им блоки файловой системы не будут полностью освобождены, пока сохраняется открытая ссылка на этот файл.Найти открытые удалённые файлы можно через:
sudo lsof +L1
Например, в выводе может быть:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NAME
java 2451 app 12w REG 8,1 15G 0 /var/log/app/application.log (deleted)
NLINK=0 означает, что ссылок из каталогов на inode больше нет, а 12w — файловый дескриптор, открытый на запись. Процесс при этом продолжает работать с прежним файлом даже после rm.Проверить, куда указывает дескриптор, и посмотреть его параметры можно через
/proc:readlink /proc/2451/fd/12
cat /proc/2451/fdinfo/12
Именно поэтому
du и df могут показывать разные значения. du считает файлы, доступные при обходе дерева каталогов, а df показывает занятые блоки файловой системы, включая блоки удалённых файлов, которые всё ещё удерживаются процессами.Сравнить показания можно так:
du -xhd1 /var
df -h /var
Чтобы штатно освободить место, приложение должно закрыть старый открытый файл. Если оно не поддерживает повторное открытие журналов, обычно достаточно штатного перезапуска сервиса:
systemctl restart имя-сервиса
Для постоянно работающих служб предпочтительнее использовать поддерживаемый приложением механизм повторного открытия журналов без полного перезапуска. Например, nginx умеет переоткрывать лог-файлы:
nginx -s reopen
Поэтому для ротации журналов обычно используют
logrotate вместе с поддерживаемым приложением механизмом reopen. copytruncate тоже применяется, когда приложение не умеет переоткрывать лог, но у него есть недостаток: между копированием файла и его обнулением существует небольшое окно, в котором часть новых записей может быть потеряна.В аварийной ситуации удалённый файл можно обнулить через его открытый файловый дескриптор:
sudo sh -c ': > /proc/2451/fd/12'
Но это именно аварийный приём. Если процесс пишет без
O_APPEND, сохранённая позиция записи после truncate может остаться далеко за новым концом файла. Последующая запись тогда способна создать разреженную область — sparse hole.Проверить флаги открытого дескриптора и текущую позицию можно через:
cat /proc/2451/fdinfo/12
Расхождение между
du и df не всегда связано именно с открытыми удалёнными файлами. Но если перед этим был удалён большой активный журнал, одна из первых диагностических команд:sudo lsof +L1
🔥 Если после
rm место не освободилось, процесс, скорее всего, продолжает удерживать удалённый файл открытым. Блоки будут окончательно освобождены, когда исчезнут все открытые ссылки на него.🚪 Linux Ready | #практика