Ответ
Ошибка EMFILE (Too many open files) возникает, когда процесс превышает лимит на количество одновременно открытых файловых дескрипторов. В Linux всё является файлом: сетевые сокеты, пайпы, реальные файлы, устройства — все они используют дескрипторы.
Основные причины в DevOps-контексте:
- Утечка дескрипторов: Сервис (например, веб-сервер или контейнер) не закрывает соединения или файлы после использования.
- Недостаточный лимит: Лимиты по умолчанию (
ulimit -n= 1024) малы для высоконагруженных приложений (базы данных, прокси, API-гейтвеи). - Растущая нагрузка: Внезапный всплеск трафика может исчерпать лимит.
Диагностика и решение:
-
Найти проблемный процесс и проверить его лимиты:
# Узнать PID процесса (например, nginx) pid=$(pgrep nginx | head -1) # Посмотреть текущее количество открытых дескрипторов ls -l /proc/$pid/fd | wc -l # Посмотреть лимиты для процесса cat /proc/$pid/limits | grep "open files" -
Повысить лимиты:
- Временное решение для сессии:
ulimit -n 65535 - Постоянное решение через systemd (для сервиса):
# /etc/systemd/system/your-service.service.d/limits.conf [Service] LimitNOFILE=65535 - Глобальное решение для системы: Изменить
/etc/security/limits.confи перелогиниться.
- Временное решение для сессии:
-
Проверить системный максимум:
cat /proc/sys/fs/file-max # Если нужно увеличить (временно) sysctl -w fs.file-max=2097152
Профилактика: Мониторинг метрик open_fds и max_fds (например, в Prometheus через node_exporter) для ключевых сервисов.
Ответ 18+ 🔞
А, блядь, вот эта ошибка — EMFILE! Знакомо, да? Процессу говорят: «Открой файл», а он такой: «Не могу, руки закончились». В линуксе же всё — файл: сокеты, пайпы, реальные файлы — на всё нужен дескриптор, а их, сука, лимит.
Откуда эта хрень обычно лезет в продакшене:
- Утечка, как из дырявого ведра: Сервис (ну, тот же nginx или какая-нибудь API-шняга) открыл соединение, отработал, а закрыть забыл — дескриптор болтается. И так по кругу, пока лимит не кончится. Распиздяйство, одним словом.
- Лимиты дефолтные — просто смех: По умолчанию-то часто 1024. Это для современного сервиса, который тысячи соединений в секунду жуёт? Да он, блядь, за секунду упрётся! Особенно всякие базы или гейтвеи.
- Внезапный пиздец (трафик): Ни с того ни с сего накатила волна запросов — и всё, приехали, лимит исчерпан. Ёпта.
Что делать, когда уже накрылось:
-
Сначала ищем виноватого и смотрим, насколько ему тесно:
# Находим PID процесса (допустим, nginx'а) pid=$(pgrep nginx | head -1) # Считаем, сколько файловых ручек он уже оторвал ls -l /proc/$pid/fd | wc -l # Смотрим, какой у него потолок по лимитам cat /proc/$pid/limits | grep "open files"Если число открытых дескрипторов впритык к лимиту — вот он, корень зла.
-
Поднимаем потолок, чтобы не бился головой:
- Быстро, на живую (чтоб не падало):
ulimit -n 65535. Но это до перезагрузки. - Надежно, через systemd (чтоб навсегда запомнил):
# Создаём файл /etc/systemd/system/your-service.service.d/limits.conf [Service] LimitNOFILE=65535Потом
systemctl daemon-reloadи перезапуск сервиса. - Всем сестрам по серьгам (глобально в системе): Ковыряем
/etc/security/limits.conf, но тут надо перелогиниться или перезагрузиться — волнение ебать.
- Быстро, на живую (чтоб не падало):
-
Глянем, а не упёрлись ли мы в системный максимум вообще:
cat /proc/sys/fs/file-max # Если мало, подкрутим (опять же, временно) sysctl -w fs.file-max=2097152
Чтобы не охуевать каждый раз: Поставь мониторинг на метрики open_fds и max_fds (через того же node_exporter в Prometheus). Увидишь, что график ползёт к потолку — уже знаешь, где ковырять. Предупреждён — значит, не обосрёшься в самый ответственный момент.