Как найти большие файлы, которые были удалены, но все еще открыты в приложении? Как удалить такой файл, даже если процесс открыт?
Ситуация такова, что мы запускаем процесс, который заполняет файл журнала с невероятной скоростью. Я знаю причину, и я могу это исправить. До тех пор я хотел бы rm или очистить файл журнала без остановки процесса.
Простое выполнение rm output.log
удаляет только ссылки на файл, но оно продолжает занимать место на диске, пока процесс не будет завершен. Хуже того, после того, rm
как я не смог найти файл или его размер! Есть ли способ найти файл и, возможно, очистить его, даже если он еще открыт в другом процессе?
Я имею в виду операционные системы на основе Linux, такие как Debian или RHEL.
files
process
logs
disk-usage
open-files
dotancohen
источник
источник
lsof -p <pid>
для отображения открытых файлов и их размеров. Удаленный файл будет иметь(deleted)
рядом с ним. Удаленный файл будет связан,/proc/<pid>/fd/1
вероятно, в. Я не знаю, как заставить процесс прекратить запись в свой файловый дескриптор, не завершив его. Я думаю, что это будет зависеть от процесса.rm
файлов ed, которые все еще открыты?lsof | grep "(deleted)"
. Когда больше нет процессов, удерживающих открытый файл открытым, ядро освобождает блоки inode и disk. Процессы не имеют «обработчиков», с помощью которых они могут получать уведомления о том, что открытый, по существу заблокированный файл был удален с диска.lsof | grep '(deleted)'
работает и в Linux. В Linux вы можете получать уведомления об удалении файлов (даже файлы, которые уже не имеют записей в каком-либо каталоге, кроме / proc / some-pid / fd) с помощью механизма inotify (событие IN_DELETE_SELF)somefile
и открыл его в VIM, а затемrm
редактировал в другом процессе bash. Затем я запускаю,lsof | grep somefile
и его там нет, хотя файл открыт в VIM.Ответы:
Если вы не можете убить свое приложение, вы можете усечь его вместо удаления файла журнала, чтобы освободить место. Если файл не был открыт в режиме добавления (с помощью
O_APPEND
), то этот файл будет иметь такой же большой размер, как и в следующий раз, когда приложение записывает в него (хотя с лидирующей частью, разреженной и выглядящей так, как будто она содержит NUL-байты), но с пробелом будет исправлено (это не относится к файловым системам HFS + в Apple OS / X, которые не поддерживают разреженные файлы).Чтобы усечь это:
Если он уже был удален, в Linux вы можете обрезать его, выполнив:
Где
$pid
находится идентификатор процесса, в котором открыт файл, и$fd
один дескриптор файла, в котором он был открыт (в котором вы можете проверитьlsof -p "$pid"
.Если вы не знаете pid и ищете удаленные файлы, вы можете сделать:
lsof -nP +L1
, как упомянуто @ user75021, является еще лучшей (более надежной и более переносимой) опцией (перечислять файлы, которые имеют менее 1 ссылки).Или (в Linux):
Или найти большие с
zsh
:Альтернативой, если приложение динамически связано, является присоединение к нему отладчика и выполнение его вызова с
close(fd)
последующим новымopen("the-file", ....)
.источник
truncate
команда, которая делает то же самое более явно.lsof
вероятно, будет наиболее близким к переносимому решению, которое вы можете получить для просмотра списка открытых файлов. подход отладчика для закрытия fd под ногами приложения также должен быть достаточно переносимым.df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud
(и затем легко отправлять сигналы нарушителям, чтобы заставить их освободить fd)lsof +L1
. На странице руководства lsof: «Спецификация формы+L1
выберет открытые файлы, которые не были связаны. Спецификация формы+aL1 <file_system>
выберет несвязанные открытые файлы в указанной файловой системе». Это должно быть немного надежнее, чем grepping.Проверьте быстрый старт здесь:
lsof
Быстрый стартЯ удивлен, что никто не упомянул файл быстрого запуска lsof (входит в состав lsof). Раздел «3.a» показывает, как найти открытые несвязанные файлы:
Например:
В системах Red Hat, чтобы найти локальную копию файла быстрого запуска, я обычно делаю это:
... или это:
источник
Это зависит от драйвера файловой системы, чтобы фактически освободить выделенное пространство, и это обычно происходит только после освобождения всех файловых дескрипторов, ссылающихся на этот файл. Таким образом, вы не сможете действительно освободить место, если не заставите приложение закрыть файл. Это означает, что нужно либо завершить его, либо «поиграть» с ним в отладчике (например, закрыть файл и убедиться, что он не был открыт / записан снова, или открыть
/dev/null
вместо него). Или вы можете взломать ядро, но я бы посоветовал против этого.Усечение файла, как предполагает Стефан, может помочь, но реальный результат также будет зависеть от вашей файловой системы (например, предварительно выделенные блоки, вероятно, будут освобождены только после закрытия файла в любом случае).
Смысл такого поведения заключается в том, что ядро не будет знать, что делать с запросами данных (как чтение, так и запись, но чтение на самом деле более важно) для такого файла.
источник
fallocate
в Linux 4.9. Не могли бы вы уточнить, под какой файловой системой и условием усечение файла не занимает место?