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

Ошибка «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
Автор
Редакция

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

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство