В терминале лимит высокий, у службы низкий: настраиваем LimitNOFILE

Инженер увеличил ulimit в своей оболочке, но служба по-прежнему получает Too many open files. Это два разных процесса с разным происхождением. Системный менеджер systemd не наследует лимиты из интерактивной сессии оператора. Проверять нужно значение у того экземпляра приложения, который выдаёт ошибку.

Начать с PID, а не с настройки

systemctl show worker.service -p MainPID -p LimitNOFILE -p LimitNOFILESoft
cat /proc/1234/limits
ls /proc/1234/fd
systemctl cat worker.service

Подставьте PID из MainPID; если файл открывает дочерний обработчик, посмотрите и его limits. В строке Max open files есть soft и hard. Рабочая мягкая граница ограничивает процесс сейчас; жёсткая определяет, до чего он может поднять мягкую без дополнительных привилегий. Наличие большого hard не означает, что приложение уже использует его.

Предположим, у процесса soft=1024, hard=524288, а открыто около 1010 дескрипторов. Это правдоподобная связь с отказом открытия. Если открыто всего 80, проверьте PID, момент измерения и точный системный код ошибки: приложение могло уже закрыть часть объектов или сообщить об ошибке другого процесса.

Задать лимит для службы

[Service]
LimitNOFILE=8192:8192

Фрагмент помещается в управляемый drop-in конкретной службы. Значение 8192 — пример бюджета, который сначала нужно обосновать количеством соединений, файлов и служебных каналов приложения. После перечитывания unit требуется новый запуск процесса. Изменение конфигурации менеджера не меняет лимиты уже запущенного PID. Параметр разобран в systemd.exec.

Не повышайте мягкий лимит выше 1024 без проверки приложения, если оно использует select: этот интерфейс имеет ограничение номера дескриптора. Современные приложения часто используют poll или epoll, но это нужно подтвердить для конкретной программы. Глобальное изменение лимитов всех служб может открыть проблему там, где её раньше не было.

Отличить законную потребность от утечки

Пусть при 200 активных заданиях число fd растёт до 1400, а после завершения возвращается к 90. Это похоже на рабочую потребность. Если после каждой одинаковой порции остаётся ещё 200 открытых файлов, повышение лимита лишь увеличит время до отказа. Снимите несколько последовательных состояний fd и классифицируйте объекты: обычные файлы, pipe, socket, eventfd.

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

Подтвердить результат

После контролируемого перезапуска снова прочитайте /proc нового PID. Повторите ту нагрузку, которая вызывала ошибку, и проверьте освобождение объектов по её завершении. В отчёте запишите конфигурацию, фактические soft/hard, пик и остаточное число fd. Так следующий инженер сможет отличить настройку от предположения.

Откройте программу Linux и Bash для DevOps-инженеров: работа с процессами и systemd помогает проверять ресурсные настройки на действующем сервисе и связывать их с причиной отказа, а не только редактировать unit.

Ещё по теме

Продолжить на практике

  • Linux и Bash для DevOps-инженеров ↗

    Linux для работы с серверами: процессы, права, systemd, сеть, диски и логи. Автоматизируйте повседневные задачи на Bash и разберите типичные сбои сервиса — от занятого порта до переполненного диска.