← Linux: администрирование
10 мин · средне · Урок 9 из 10

Файловые дескрипторы и /proc/<pid>/fd

Что такое fd, откуда берётся «too many open files» и как найти утечку дескрипторов.

Что такое файловый дескриптор

Когда процесс открывает файл, ядро выдаёт ему файловый дескриптор (fd) — небольшое число, по которому процесс дальше обращается к этому файлу. Дескриптор — это ссылка процесса на открытый ресурс, а не сам файл.

Три дескриптора есть у любого процесса с самого старта:

Дальше идут 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), включая лимит на эти самые дескрипторы.

Прошли материал до конца? Отметьте урок пройденным.