Гипотеза: удаленные, но все еще открытые файлы
Учитывая информацию, предоставленную до сих пор, и намек на наличие большого объема файлов, связанных с докером, я подозреваю, что это вызвано удаленными, но все еще открытыми файлами, то есть файлами, которые создаются программой, а затем программа удаляет путь к файловой системе, оставляя файловый дескриптор открытым.
Это может быть результатом активности Docker в файловой системе.
Принцип решения
- Выявите удаленные файлы, на которые все еще ссылаются процессы (способ см. ниже).
- В идеале раскрывайте имена и/или идентификаторы процессов, чтобы у вас были подсказки о том, что происходит.
- Закройте эти процессы, обратите внимание, что место освобождено.
- Если ничего не помогает, просто перезагрузите машину. Если пространство освобождается, это согласуется с гипотезой.
Как раскрыть информацию
Приведенные ниже команды проверят гипотезу, найдя и отобразив, какое пространство используется каким файлом.
Первый взгляд
Для общего ознакомления вы можете сделать следующее:
lsof -n | egrep -w "удалено|^КОМАНДА"
Но это также будет перечислять множество псевдофайлов только в памяти, которые не занимают никакого фактического места для хранения.
Пример:
КОМАНДА PID TID TASKCMD ПОЛЬЗОВАТЕЛЬ FD ТИП УСТРОЙСТВА РАЗМЕР/ВЫКЛ ИМЯ УЗЛА
Xorg 1183 root 78u REG 0,1 4 2058 /memfd:xshmfence (удалено)
Xorg 1183 root 85u REG 0,1 4 7182 /memfd:xshmfence (удалено)
Xorg 1183 root 92u REG 0,1 4 7137 /memfd:xshmfence (удалено)
Xorg 1183 root 94u REG 0,1 4 7870 /memfd:xshmfence (удалено)
Отфильтрованный простой список
Это фильтрует и в основном показывает реальные файлы:
lsof -F "sn" -lnPX -M | sed -n 's|^n/|/|p' | grep удален | egrep -v '^/(dev/shm|memfd:|proc)' | LC_ALL=С сортировать -n | уникальный
Пример:
/tmp/#someinodenumber (удален)
Полная информация с размером, именем процесса и задачи
Это более интересно: в нем будут перечислены все файлы вместе с занимаемым ими пространством в байтах и т. д.
Во-первых, медленная часть, сбор данных
# Вы можете запустить эту часть от имени пользователя root, чтобы убедиться, что все сообщается
lsof -F "ctsupMin" -lnPX -M >|/tmp/lfosoutput
Затем обработайте и отформатируйте для красивого отображения, завершите и отсортируйте по увеличению размера.
# Можно запускать как обычный пользователь, root не нужен
{ echo "РАЗМЕР^UID^PID^ИМЯ ПРОЦЕССА^ИМЯ ЗАДАЧИ^INODE^ПУТЬ"
</tmp/lfosoutput \
python3 -c $'import sys; е={}
def g(c): вернуть f.get(c,"(неизвестно)")
для строки в sys.stdin:
с=строка[0] ; г=строка[1:].rstrip() ; е [с] = г
если c=="n" и f["t"]=="REG" \
и "(удалено)" в f["n"] \
а не f["n"].startswith("/memfd:") \
а не f["n"].startswith("/dev/shm") :
print(f'\''{g("s")}^{g("u")}^{g("p")}^\"{g("c")}\"^\"{ г("М")}\"^{г("я")}^{г("п")}'\'')
е={}' \
| LC_ALL=С сортировать -n | уникальный
echo "РАЗМЕР^UID^PID^ИМЯ ПРОЦЕССА^ИМЯ ЗАДАЧИ^INODE^ПУТЬ"
} | столбец -t -s '^'
Пример вывода: файл размером 36 мегабайт, используемый Firefox.
РАЗМЕР UID PID НАЗВАНИЕ ПРОЦЕССА НАЗВАНИЕ ЗАДАЧИ ИНОД ПУТЬ
36012032 1234 12345 "Isolated Web Co" "StyleThread#2" 1234567 /tmp/mozilla-temp-12345 (удален)
РАЗМЕР UID PID НАЗВАНИЕ ПРОЦЕССА НАЗВАНИЕ ЗАДАЧИ ИНОД ПУТЬ
(На самом деле таких строк много, это только пробная строка.)
Проверяем, действительно ли скрипт обнаруживает такие файлы, создавая один
В другом терминале скопируйте и вставьте это:
# Запустить интерактивный интерпретатор Python
питон3
# Теперь на Питоне
n="/tmp/любое_имя_файла_вам_хочу"
f = открыть (n, режим = 'а')
импорт ОС
os.unlink(n)
f.write("какое-то предложение")
f.flush()
# Не выходите сейчас, иначе файл действительно исчезнет
В первом терминале вы можете выполнить оба описанных выше шага (медленный lsof, затем часть форматирования).
И пока процесс python, указанный выше, жив, сообщается эта строка:
РАЗМЕР UID PID НАЗВАНИЕ ПРОЦЕССА НАЗВАНИЕ ЗАДАЧИ ИНОД ПУТЬ
13 1000 1387343 "python3" "gdbus" 1308894 /tmp/любое_имя_файла_вам_хочу (удалено)
РАЗМЕР UID PID НАЗВАНИЕ ПРОЦЕССА НАЗВАНИЕ ЗАДАЧИ ИНОД ПУТЬ
Затем вы можете выйти из интерпретатора Python выше (нажмите Control-D
или введите выход(0)
). Если вы запустите обе части (медленный lsof, а затем часть форматирования), вы увидите, что тестовый файл больше не появляется.
Приведенный выше сценарий можно изменить для записи огромных объемов данных (например, сотен гигабайт), и с помощью ваших обычных инструментов вы увидите, что пространство действительно освобождается только после того, как процесс создания закроет файловый дескриптор. Завершения процесса достаточно, чтобы обеспечить закрытие файлового дескриптора.
Вернемся к вашему делу
Запустив это, вы, скорее всего, увидите имена процессов, имена задач и файлы. Либо несколько больших файлов, таких как изображения, которые Docker извлек из сети, либо огромное количество маленьких файлов, опять же, из Docker.
Или что-то другое.
Пожалуйста, скажите, поможет ли это вам.