Файловые дескрипторы и /proc/<pid>/fd
Что такое fd, откуда берётся «too many open files» и как найти утечку дескрипторов.
Что такое файловый дескриптор
Когда процесс открывает файл, ядро выдаёт ему файловый дескриптор (fd) — небольшое число, по которому процесс дальше обращается к этому файлу. Дескриптор — это ссылка процесса на открытый ресурс, а не сам файл.
Три дескриптора есть у любого процесса с самого старта:
0— stdin, стандартный ввод,1— stdout, стандартный вывод,2— stderr, поток ошибок.
Дальше идут 3, 4, и так далее: это файлы, сетевые соединения (сокеты),
пайпы, которые процесс открыл в работе. Для ядра всё это «файлы», поэтому
дескриптор один на все случаи.
/proc//fd
Открытые дескрипторы процесса видны в /proc/<pid>/fd/: каждый
дескриптор там симлинк на то, что открыто:
$ ls -l /proc/812/fd
lrwx------ 0 -> /dev/null
lrwx------ 1 -> /var/log/app.log
lrwx------ 2 -> /var/log/app.log
lrwx------ 3 -> socket:[48213]
lrwx------ 4 -> /var/lib/app/data.db
Видно, что stdout (1) и stderr (2) ушли в лог, есть открытый сокет и файл базы. Посчитать, сколько дескрипторов держит процесс:
ls /proc/812/fd | wc -l
«too many open files»
У каждого процесса есть лимит на число открытых дескрипторов. Когда программа открывает файлы или соединения и забывает их закрывать, fd накапливаются. Это утечка дескрипторов. В какой-то момент процесс упирается в лимит и падает с ошибкой:
Error: EMFILE: too many open files
Это частая авария у сетевых сервисов: каждое соединение — дескриптор, и если их не закрывать, они копятся. Диагностика простая: смотреть, как растёт число fd у процесса:
ls /proc/812/fd | wc -l # выполнить несколько раз: число всё растёт?
Если число постоянно растёт и не возвращается, это утечка, и проблема в коде, который не закрывает ресурсы.
Связь с inode
Здесь сходится то, что было раньше. Удалённый, но открытый файл (из урока
про диск) — это как раз случай, когда имя из каталога убрали, но процесс
держит дескриптор на inode. Данные живут, пока жив дескриптор. Поэтому
du файла не видит, а место занято: на него ещё ссылается fd.
Что важно запомнить
Файловый дескриптор — число-ссылка процесса на открытый файл, сокет или
пайп. 0/1/2 — stdin/stdout/stderr, дальше идут открытые ресурсы.
Открытые дескрипторы процесса видны в /proc/<pid>/fd/. Растущее число
fd, которое не возвращается, означает утечку; рано или поздно ловит «too many
open files».
Удалённый открытый файл держится дескриптором: место не освобождается, пока fd жив.
В следующем уроке разберём лимиты процессов (ulimit), включая лимит на эти
самые дескрипторы.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс