Too many open files в журнале службы
Сообщение Too many open files (номер 24, EMFILE) значит, что служба исчерпала свой предел открытых файловых дескрипторов. Под дескрипторы попадают не только файлы, но и сетевые соединения — поэтому предел первым достигают нагруженные серверы и службы с утечкой.
Что это значит
У службы под systemd предел задаётся в unit-файле параметром LimitNOFILE=, и настройки в /etc/security/limits.conf на неё не действуют: тот файл относится к входу пользователей в систему. Это первая причина, по которой «я же поднял лимит» не срабатывает.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Предел в unit-файле слишком мал для нагрузки
Значение по умолчанию (обычно 1024 мягкий предел) рассчитано на скромные службы. Веб-сервер, база или прокси на тысячах соединений исчерпывают его быстро.
-
Утечка дескрипторов в самой программе
Программа открывает файлы или соединения и не закрывает их. Тогда любой предел исчерпается — просто через большее время. Признак: число дескрипторов растёт монотонно.
-
Исчерпан общесистемный предел
Кроме предела процесса есть общий предел системы. При его исчерпании начинают отказывать все службы сразу.
-
Мягкий предел не поднят до жёсткого
Программа видит мягкий предел. Если в unit-файле задать только жёсткий, программа продолжит упираться в мягкий, пока сама его не повысит.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Сколько дескрипторов держит служба прямо сейчас. Сравнение с пределом сразу даёт ответ.
PID=$(systemctl show -p MainPID --value myapp.service); ls /proc/$PID/fd | wc -lДействующие пределы именно у службы, а не у вашего сеанса.
systemctl show myapp.service -p LimitNOFILE -p LimitNOFILESoftТри числа: занято, свободно из занятых, общий предел системы.
cat /proc/sys/fs/file-nrРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Значение по умолчанию (обычно 1024 мягкий предел) рассчитано на скромные службы. Веб-сервер, база или прокси на тысячах соединений исчерпывают его быстро.
- Как проверить
-
Посмотрите действующий предел и текущее использование.
systemctl show myapp.service -p LimitNOFILE -p LimitNOFILESoft cat /proc/$(systemctl show -p MainPID --value myapp.service)/limits | grep -i "open files"
- Как исправить
-
Поднимите предел в unit-файле через drop-in и перезапустите службу. Для веб-серверов и баз обычное значение — от 16384 до 65535.
sudo systemctl edit myapp.service # [Service]\nLimitNOFILE=65535 sudo systemctl restart myapp.service
- Почему происходит
- Программа открывает файлы или соединения и не закрывает их. Тогда любой предел исчерпается — просто через большее время. Признак: число дескрипторов растёт монотонно.
- Как проверить
-
Посмотрите, сколько дескрипторов держит процесс сейчас, и сравните через несколько минут.
PID=$(systemctl show -p MainPID --value myapp.service); ls /proc/$PID/fd | wc -l sudo ls -l /proc/$PID/fd | awk "{print \$NF}" | sort | uniq -c | sort -rn | head
- Как исправить
- Разбирайтесь с программой: вторая команда показывает, какого рода дескрипторы копятся. Поднятие предела тут лишь отложит сбой.
- Почему происходит
- Кроме предела процесса есть общий предел системы. При его исчерпании начинают отказывать все службы сразу.
- Как проверить
-
Сравните использованное с допустимым.
cat /proc/sys/fs/file-nr sysctl fs.file-max
- Как исправить
-
Поднимите
fs.file-maxчерез файл в /etc/sysctl.d и найдите службу, которая держит основную массу дескрипторов.echo "fs.file-max = 2097152" | sudo tee /etc/sysctl.d/99-files.conf && sudo sysctl --system
- Почему происходит
- Программа видит мягкий предел. Если в unit-файле задать только жёсткий, программа продолжит упираться в мягкий, пока сама его не повысит.
- Как проверить
-
Посмотрите оба значения.
systemctl show myapp.service -p LimitNOFILE -p LimitNOFILESoft
- Как исправить
-
Задавайте предел одним числом — тогда мягкий и жёсткий совпадут, — либо явной парой:
LimitNOFILE=65535:65535.
Пример вывода
Веб-сервер исчерпал предел дескрипторов под нагрузкой. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
● nginx.service - A high performance web server and a reverse proxy server
Active: active (running) since Mon 2026-09-15 08:00:01 MSK; 6h ago
nginx[1120]: 2026/09/15 14:02:31 [crit] 1120#1120: accept4() failed (24: Too many open files)
nginx[1120]: 2026/09/15 14:02:31 [alert] 1120#1120: *8812 socket() failed (24: Too many open files)
Здесь служба продолжает работать, но отказывает клиентам. Такие сообщения стоит замечать до того, как она упадёт.
Связанные ошибки
- status=205/LIMITS в systemd Код 205/LIMITS: systemd не смог применить ограничения ресурсов из Limit*=. Обычно значение недопустимо или превышает жёсткий предел.
- status=202/FDS в systemd Код 202/FDS: systemd не смог закрыть лишние файловые дескрипторы или настроить переданные. Причины и проверка.
- Failed with result 'resources' Состояние resources: systemd не смог выделить ресурсы для запуска службы. Чем отличается от кодов 200-й группы и что проверять.
- No space left on device в журнале службы Нет места на устройстве: разбор по свободным блокам, по inode, по журналу systemd и по удалённым, но открытым файлам.
- Пределы ресурсов в unit-файле не применяются Почему limits.conf не действует на службы и как проверить действующие пределы процесса.
- A start job is running: загрузка висит на одной службе Загрузка останавливается с обратным отсчётом: служба не укладывается в таймаут. Как найти виновника и не ждать.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Apache: Invalid command — не включён модуль Apache не запускается: директива требует модуль, который не подключён. Как найти нужный модуль и включить.
Где встречается чаще всего
Источники
-
systemd.exec(5)
LimitNOFILE= и его отношение к limits.conf. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено на unit с LimitNOFILE=64 под нагрузкой; счёт дескрипторов через /proc.