Гид по технологиям

Ошибка «Too many open files» в Linux: причины и как исправить

8 min read Linux Обновлено 24 Dec 2025
Too many open files в Linux — причины и исправление
Too many open files в Linux — причины и исправление

Приложение Терминал на Linux.

Быстрые ссылки

  • Что такое ошибка Too Many Open Files?

  • Почему открывается так много файлов?

  • Как проверить лимиты дескрипторов

  • Как увеличить soft-лимит

  • Как навсегда изменить лимит файлов

  • Помните, что всё — файл

Краткое содержание

Ошибка «Too many files open» означает, что процесс попытался открыть больше файлов, чем ему разрешено по текущему лимиту дескрипторов (обычно 1024). Можно временно поднять лимит через ulimit -n, но для постоянного изменения на systemd-системах нужно править systemd-конфигурации или unit-файлы. Прежде чем менять лимиты глобально, проверьте, не вызывает ли утечку файлов конкретный процесс.

Что такое ошибка Too Many Open Files?

Ядро Linux контролирует использование ограниченных системных ресурсов: память, процессы, файловые дескрипторы и т. д. Для каждого процесса существует ограничение на число открытых файлов (файловых дескрипторов). Когда процесс достигает этого предела, дальнейшие попытки открытия файлов приводят к ошибке «Too many files open» или к возврату errno EMFILE в программах.

Определения в одну строку:

  • Файловый дескриптор — целое число, которое ядро выделяет процессу при открытии файла или ресурса.
  • Soft-лимит — текущая граница, которую может менять пользователь до значения hard-лимита.
  • Hard-лимит — максимальная верхняя граница, которую может изменить только root.

Если вы видите ошибку в терминале или в логах, значит процесс исчерпал доступные дескрипторы и не может открыть дополнительные файлы, сокеты или потоки ввода-вывода.

Почему открывается так много файлов?

Linux абстрагирует множество сущностей как «файлы»: реальные файлы, каталоги, сокеты, каналы (pipes), символьные и блочные устройства, открытые библиотеки и т. д. Это даёт мощный единый интерфейс, но и увеличивает потребление дескрипторов.

Типичные причины большого количества открытых файлов:

  • Демоны или серверы (веб, БД, прокси) обслуживают много соединений.
  • Программа неправильно закрывает файловые дескрипторы (file descriptor leak).
  • Массовая обработка файлов (пакетная обработка, индексация).
  • Множество одновременных потоков/процессов, каждый открывает ресурсы.
  • Библиотеки создают временные дескрипторы (например, для логирования или доступа к ресурсам).

Даже если вы физически не открыли тысячи файлов, многие сервисы и подсистемы ОС занимают дескрипторы. Поэтому наблюдаемый счётчик включает системные дескрипторы помимо ваших приложений.

Как проверить лимиты дескрипторов

Системный максимум дескрипторов показывает:

cat /proc/sys/fs/file-max

Это теоретический предел ядра (огромное число на 64‑битных системах). Практические лимиты для процессов задаются через ulimit и systemd.

Проверить текущий soft-лимит (открытые файлы) для текущей оболочки:

ulimit -n

Проверить текущий hard-лимит:

ulimit -Hn

Показать soft- и hard-лимит вместе:

ulimit -Sn

Предел процессов для пользователя:

ulimit -u

Практическая диагностика: если вы хотите увидеть, какие файлы открыты конкретным процессом, используйте lsof:

lsof -p 

Пример: мы скомпилировали тестовую утилиту open-Files, которая открывает файлы до отказа и затем ждёт нажатия клавиши. После запуска она печатает PID. Чтобы посмотреть её дескрипторы:

lsof -p 11038

Списки stdin, stdout и stderr в выводе lsof

Чтобы найти процессы, которые используют больше всего дескрипторов, выполните:

lsof | awk '{ print $1 " " $2; }' | sort -rn | uniq -c | sort -rn | head -15

Эта команда показывает 15 наиболее «жадных» к дескрипторам процессов. Подстройте head -15, если нужно больше или меньше строк.

Процессы, использующие наибольшее число дескрипторов

Обратите внимание: процессам при старте автоматически выделяются три стандартных дескриптора: 0 (STDIN), 1 (STDOUT), 2 (STDERR). Поэтому при подсчёте открытых дескрипторов ожидаемо видеть «на 3 меньше» от лимита.

Как увеличить soft-лимит (временно для сессии)

Чтобы временно увеличить лимит в текущей оболочке:

ulimit -n 2048

После этого процессы, запущенные из этой оболочки, унаследуют новое значение. В примере тестовая утилита успешно открывает 2045 файлов (2048 минус 3 стандартных дескриптора).

Важно: этот способ действует только пока открыта текущая сессия или терминал. Новые логины получат прежние значения, если не изменить конфигурацию глобально.

Как навсегда изменить лимит файлов (systemd)

На современных дистрибутивах с systemd рекомендуемый способ — править systemd-настройки, а не старые /etc/security/limits.conf, так как они работают не всегда для графических сессий.

  1. Отредактируйте глобальный systemd-конфиг:
sudo nano /etc/systemd/system.conf

Найдите строку с DefaultLimitNOFILE и уберите «#» в начале, установите новые значения, например:

DefaultLimitNOFILE=4096:8192

Первое число — soft, второе — hard. Если указано одно число, оно задаёт и soft, и hard.

  1. Отредактируйте пользовательские настройки systemd:
sudo nano /etc/systemd/user.conf

Аналогично поменяйте DefaultLimitNOFILE.

  1. Перезапустите systemd так, чтобы он перечитал конфигурацию:
sudo systemctl daemon-reexec

Или выполните перезагрузку системы.

Проверьте новое значение в новой сессии:

ulimit -n

Альтернативный и часто предпочтительный способ — задавать лимит для конкретного systemd-сервиса. В unit-файле сервиса можно прописать:

[Service]
LimitNOFILE=65536

После правки unit-файла выполните:

sudo systemctl daemon-reload
sudo systemctl restart 

Это безопаснее, чем поднимать глобальные лимиты, и даёт точечный контроль.

Примечание о /etc/security/limits.conf: в системах без systemd или при использовании специализированных PAM-настроек правки limits.conf остаются релевантными, но поведение графических сессий (Display Manager) и systemd может игнорировать эти значения.

Практические советы по изменению лимитов

  • Не поднимайте глобальные лимиты по умолчанию на все службы без причины. Лучше регулируйте лимиты для сервисов, которые действительно обслуживают много соединений (nginx, PostgreSQL, брокеры сообщений).

  • Проверяйте, нет ли утечек дескрипторов в коде: забытые close(), неоднократные open без закрытия, неверное использование файловых дескрипторов при fork/exec.

  • Если ошибка появляется внезапно у сервиса — сначала перезапустите его и посмотрите, сколько дескрипторов он использует через lsof или через /proc//fd.

  • Для долгоживущих процессов настройте мониторинг количества открытых дескрипторов (например, экспортируйте в Prometheus через node_exporter или собирайте в Zabbix).

Когда повышение лимита не поможет

  • Если приложение страдает от реальной утечки дескрипторов (не закрывает их), повышение лимита лишь отложит проблему. Корректное решение — исправить код.

  • Если ресурсная проблема — не в дескрипторах, а в памяти или CPU, увеличение NOFILE ничего не изменит.

  • Если системный файл-дескрипторный пул исчерпан системой в целом (файл /proc/sys/fs/file-max), нужно анализировать нагрузку и возможную уязвимость.

Альтернативные подходы

  • Ограничьте число одновременных соединений в вашем сервисе (на уровне приложения или прокси), чтобы уменьшить пиковое потребление дескрипторов.

  • Используйте пул соединений и переиспользование дескрипторов там, где возможно.

  • Включите логирование открытия/закрытия дескрипторов в режиме отладки для поиска утечек.

  • Для высоконагруженных систем распределите нагрузку на несколько процессов/серверов.

Ментальные модели и практические эвристики

  • «Soft = текущая цель, hard = потолок» — можно повышать soft до hard без root.

  • «Каждый сетевой сокет — это файл» — при проектировании серверов считайте открытые соединения как потребление файловых дескрипторов.

  • «Почти всё в Linux — файл» — это помогает понимать, почему дескрипторы расходуются быстро.

Фактбокс: ключевые числа

  • Стандартный soft-лимит для большинства дистрибутивов: 1024.

  • Стандартный набор трёх системных дескрипторов: 0 (stdin), 1 (stdout), 2 (stderr).

  • LimitNOFILE в unit-файле systemd управляет лимитом на уровне сервиса.

  • /proc/sys/fs/file-max показывает системный «теоретический» максимум.

Руководство действий (SOP) при обнаружении ошибки

  1. Зафиксировать время появления ошибки и сервисы, затронутые ошибкой.

  2. Найти процессы с наибольшим количеством открытых файлов:

lsof | awk '{ print $1 " " $2; }' | sort -rn | uniq -c | sort -rn | head -15
  1. Для подозрительного процесса получить список открытых дескрипторов:
lsof -p 
ls -l /proc//fd
  1. Если это легитимная нагрузка — увеличить LimitNOFILE в unit-файле и перезапустить сервис.

  2. Если это утечка — перезапустить сервис и включить детальную трассировку, профайлинг или отладочный лог.

  3. При необходимости поднять DefaultLimitNOFILE глобально, соблюдая осторожность.

  4. Настроить мониторинг и оповещения по числу открытых файлов.

Чек-лист для ролей

Для админа сервера:

  • Проверил lsof и /proc//fd.
  • Перезапустил проблемный сервис и проверил поведение.
  • Если нужно, изменил LimitNOFILE в unit-файле и выполнил daemon-reload.

Для разработчика приложения:

  • Проверил правильность закрытия файлов/сокетов (close(), context manager в Python и т. п.).
  • Добавил логирование создания/закрытия дескрипторов в отладке.
  • Написал и прогнал тесты на утечки дескрипторов.

Для архитектора/разработчика системы:

  • Оценил ожидаемую нагрузку и рассчитанные лимиты.
  • Спроектировал горизонтальное масштабирование при необходимости.
  • Настроил наблюдение (SLI/SLO по количеству дескрипторов/соединений).

Примеры конфигураций systemd

Пример изменения лимита для конкретного сервиса (например, myapp.service):

# /etc/systemd/system/myapp.service.d/limits.conf
[Service]
LimitNOFILE=65536

После добавления файла выполните:

sudo systemctl daemon-reload
sudo systemctl restart myapp

Пример правки глобального конфига:

# /etc/systemd/system.conf
DefaultLimitNOFILE=4096:8192

И затем:

sudo systemctl daemon-reexec

Диагностика и тесты приёмки

Критерии приёмки после повышения лимита:

  • Сервис больше не выдаёт ошибку «Too many files open» при типичной нагрузке.
  • Количество открытых дескрипторов у сервиса соответствует ожидаемому (см. lsof).
  • Наблюдение не показывает роста числа открытых дескрипторов со временем (нет утечки).

Тестовые сценарии:

  • Запустить нагрузочный тест для сервиса, наблюдать за lsof и /proc//fd.
  • Повторять тест параллельно для разных значений LimitNOFILE, фиксируя поведение.

Совместимость и примечания для разных окружений

  • На systemd-базированных дистрибутивах корректный способ — systemd-правки (см. выше).

  • На старых системах без systemd или на некоторых контейнерных окружениях правки systemd не применимы.

  • В WSL (Windows Subsystem for Linux) и в некоторых контейнерах поведение limits.conf и systemd может отличаться; тестируйте в целевой среде.

Безопасность и последствия

Поднятие глобальных лимитов значит, что процессы смогут открывать больше ресурсов, что потенциально увеличивает последствия уязвимостей в программах. Ограничивайте лимиты только там, где это необходимо, и по возможности применяйте их на уровне сервиса.

Краткий глоссарий

  • Дескриптор: целое число, обозначающее открытый ресурс в процессе.
  • Soft-лимит: текущее разрешённое значение; может повышаться пользователем до hard-лимита.
  • Hard-лимит: верхняя граница; изменение доступно только root.
  • LimitNOFILE: директива systemd, задающая лимит открытых файлов для сервиса.

Итог

Ошибка «Too many files open» — сигнал о достижении лимита файловых дескрипторов. Для быстрой локальной отладки используйте lsof и ulimit. Для устойчивого решения задавайте лимиты целенаправленно: используйте LimitNOFILE в unit-файлах systemd для сервисов или меняйте DefaultLimitNOFILE глобально, если это обосновано. Всегда сначала исключайте утечки дескрипторов в коде, прежде чем бездумно повышать системные лимиты.

Important: перед глобальными изменениями тестируйте поведение в staging и настройте мониторинг количества открытых файлов.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Установка Git на Windows
Разработка

Установка Git на Windows

Udio — создавайте треки по 30 секунд
AI музыка

Udio — создавайте треки по 30 секунд

Как включить или отключить чувствительный контент в X
соцсети

Как включить или отключить чувствительный контент в X

Как сделать бэкап iCloud Photos на Mac
Резервное копирование

Как сделать бэкап iCloud Photos на Mac

Как изменить звук зарядки iPhone
Гайды

Как изменить звук зарядки iPhone

Как приостановить обновления Windows 10
Windows

Как приостановить обновления Windows 10