Гипотеза: удаленные, но все еще открытые файлы
Учитывая информацию, предоставленную до сих пор, и намек на наличие большого объема файлов, связанных с докером, я подозреваю, что это вызвано удаленными, но все еще открытыми файлами, то есть файлами, которые создаются программой, а затем программа удаляет путь к файловой системе, оставляя файловый дескриптор открытым.
Это может быть результатом активности Docker в файловой системе.
Принцип решения
- Выявите удаленные файлы, на которые все еще ссылаются процессы (способ см. ниже).
- В идеале раскрывайте имена и/или идентификаторы процессов, чтобы у вас были подсказки о том, что происходит.
- Закройте эти процессы, обратите внимание, что место освобождено.
- Если ничего не помогает, просто перезагрузите машину. Если пространство освобождается, это согласуется с гипотезой.
Как раскрыть информацию
Приведенные ниже команды проверят гипотезу, найдя и отобразив, какое пространство используется каким файлом.
Первый взгляд
Для общего ознакомления вы можете сделать следующее:
lsof -n | egrep -w "deleted|^COMMAND"
Но это также будет перечислять множество псевдофайлов только в памяти, которые не занимают никакого фактического места для хранения.
Пример:
COMMAND PID TID TASKCMD USER FD TYPE DEVICE SIZE/OFF NODE NAME
Xorg 1183 root 78u REG 0,1 4 2058 /memfd:xshmfence (deleted)
Xorg 1183 root 85u REG 0,1 4 7182 /memfd:xshmfence (deleted)
Xorg 1183 root 92u REG 0,1 4 7137 /memfd:xshmfence (deleted)
Xorg 1183 root 94u REG 0,1 4 7870 /memfd:xshmfence (deleted)
Отфильтрованный простой список
Это фильтрует и в основном показывает реальные файлы:
lsof -F "sn" -lnPX -M | sed -n 's|^n/|/|p' | grep deleted | egrep -v '^/(dev/shm|memfd:|proc)' | LC_ALL=C sort -n | uniq
Пример:
/tmp/#someinodenumber (deleted)
Полная информация с размером, именем процесса и задачи
Это более интересно: в нем будут перечислены все файлы вместе с занимаемым ими пространством в байтах и т. д.
Во-первых, медленная часть, сбор данных
# You may want to run this part as root to make sure all is reported
lsof -F "ctsupMin" -lnPX -M >|/tmp/lfosoutput
Затем обработайте и отформатируйте для красивого отображения, завершите и отсортируйте по увеличению размера.
# Can be run as regular user, no need for root
{ echo "SIZE^UID^PID^PROCESS NAME^TASK NAME^INODE^PATH"
</tmp/lfosoutput \
python3 -c $'import sys ; f={}
def g(c): return f.get(c,"(unknown)")
for line in sys.stdin:
c=line[0] ; r=line[1:].rstrip() ; f[c]=r
if c=="n" and f["t"]=="REG" \
and "(deleted)" in f["n"] \
and not f["n"].startswith("/memfd:") \
and not f["n"].startswith("/dev/shm") :
print(f'\''{g("s")}^{g("u")}^{g("p")}^\"{g("c")}\"^\"{g("M")}\"^{g("i")}^{g("n")}'\'')
f={}' \
| LC_ALL=C sort -n | uniq
echo "SIZE^UID^PID^PROCESS NAME^TASK NAME^INODE^PATH"
} | column -t -s '^'
Пример вывода: файл размером 36 мегабайт, используемый Firefox.
SIZE UID PID PROCESS NAME TASK NAME INODE PATH
36012032 1234 12345 "Isolated Web Co" "StyleThread#2" 1234567 /tmp/mozilla-temp-12345 (deleted)
SIZE UID PID PROCESS NAME TASK NAME INODE PATH
(На самом деле таких строк много, это только пробная строка.)
Проверяем, действительно ли скрипт обнаруживает такие файлы, создавая один
В другом терминале скопируйте и вставьте это:
# Run python interactive interpreter
python3
# Now in Python
n="/tmp/whatever_file_name_you_want"
f=open(n,mode='a')
import os
os.unlink(n)
f.write("some sentence")
f.flush()
# Don't exit now or the file will really disappear
В первом терминале вы можете выполнить оба описанных выше шага (медленный lsof, затем часть форматирования). И пока процесс python, указанный выше, жив, сообщается эта строка:
SIZE UID PID PROCESS NAME TASK NAME INODE PATH
13 1000 1387343 "python3" "gdbus" 1308894 /tmp/whatever_file_name_you_want (deleted)
SIZE UID PID PROCESS NAME TASK NAME INODE PATH
Затем вы можете выйти из интерпретатора Python выше ( нажмите Control-D
или введите exit(0)
). Если вы запустите обе части (медленный lsof, а затем часть форматирования), вы увидите, что тестовый файл больше не появляется.
Приведенный выше сценарий можно изменить для записи огромных объемов данных (например, сотен гигабайт), и с помощью ваших обычных инструментов вы увидите, что пространство действительно освобождается только после того, как процесс создания закроет файловый дескриптор. Завершения процесса достаточно, чтобы обеспечить закрытие файлового дескриптора.
Вернемся к вашему делу
Запустив это, вы, скорее всего, увидите имена процессов, имена задач и файлы. Либо несколько больших файлов, таких как изображения, которые Docker извлек из сети, либо огромное количество маленьких файлов, опять же, из Docker.
Или что-то другое.
Пожалуйста, скажите, поможет ли это вам.