Параметры ядра, модули и лимиты: как изменить нужный уровень
Автор: Казачкин Даниил Михайлович · Обновлено
Ошибка «Too many open files» требует выяснить, какое ограничение сработало. Увеличение случайного sysctl может не изменить поведение приложения: лимит принадлежит конкретному…
Ошибка «Too many open files» требует выяснить, какое ограничение сработало. Увеличение случайного sysctl может не изменить поведение приложения: лимит принадлежит конкретному процессу, пользовательскому сеансу или группе ресурсов. Научимся находить действующий уровень и проверять изменение после нового запуска.
Сначала измерение, затем значение
Следующие команды только читают состояние:
sysctl net.ipv4.ip_forward vm.swappiness vm.max_map_count
sysctl fs.inotify.max_user_watches fs.inotify.max_user_instances
ulimit -Sn
ulimit -Hn
cat /proc/$$/limits
cat /proc/cmdlineip_forward=0 означает, что IPv4-пересылка выключена в соответствующем сетевом namespace. Для обычного клиента это нормально; маршрутизатору дополнительно нужны маршруты и правила firewall. На учебной VM изменение выполняют через sudo sysctl -w net.ipv4.ip_forward=1, а постоянное значение записывают в отдельный файл /etc/sysctl.d/60-lab-routing.conf. Применение sudo sysctl -p /etc/sysctl.d/60-lab-routing.conf ограничивает изменение этим файлом. Прочитайте значение повторно и предусмотрите возврат исходной настройки. Глобальный sysctl --system затрагивает остальные конфигурационные файлы. Порядок sysctl.d.
Swappiness описывает относительную стоимость обмена анонимной памятью и файлового ввода-вывода, а не процент заполнения RAM. Допустимый диапазон современного ядра — 0–200; ноль тоже не равен отключению swap. Значение 10 и объём памяти 4 ГБ сами по себе не образуют рекомендацию: сравнивайте задержки, PSI и активность swap на одинаковой нагрузке. Для zram условия отличаются от медленного диска. vm.max_map_count ограничивает число отображений памяти процесса; требуемое значение зависит от версии приложения. Параметры VM.
Watchers, файловые дескрипторы и служба
При System limit for number of file watchers reached проверьте сообщения программы, число её inotify-дескрипторов в /proc/PID/fd и записи /proc/PID/fdinfo. Один дескриптор может содержать много watches: подсчёт только ссылок fd не измеряет их количество. Лимиты watches и instances учитываются по пользователю; сначала исключите повторные процессы наблюдения и ненужные каталоги сборки.
Ошибка EMFILE относится к пределу дескрипторов процесса, ENFILE — к системному ресурсу открытых файлов. Сопоставьте /proc/PID/limits, число записей /proc/PID/fd и sysctl fs.file-max. Утечка дескрипторов продолжится и после увеличения предела.
ulimit -Sn 256 меняет soft limit текущего shell и его будущих потомков. Проверьте это без изменения своего терминала:
bash -c 'ulimit -Sn 256; ulimit -Sn; grep "Max open files" /proc/$$/limits'Если унаследованный hard limit ниже 256, команда закономерно завершится ошибкой. /etc/security/limits.d/ обрабатывается PAM для подходящих новых сеансов и не является общим источником настроек системной службы. Для такой службы применяют drop-in:
[Service]
LimitNOFILE=4096:8192После проверки unit нужны daemon-reload и перезапуск именно службы; затем сравните systemctl show app.service -p LimitNOFILE -p LimitNOFILESoft с /proc/новый_PID/limits. При пользовательском manager нельзя превысить его унаследованный hard limit одним параметром unit. Лимиты systemd.
Модуль и параметр загрузки — разные механизмы
lsmod показывает загруженные модули, modinfo loop — доступные сведения модуля. Отсутствие строки в lsmod не доказывает отсутствия функции: драйвер бывает встроен в ядро. В учебной VM sudo modprobe loop разрешает зависимости, а modprobe -n -v loop позволяет сначала посмотреть план. Автозагрузку задают в modules-load.d; параметры и blacklist — в modprobe.d. Blacklist подавляет обычное разрешение псевдонимов, но не гарантирует запрет явной загрузки и не выгружает уже работающий драйвер. Для раннего boot может понадобиться обновление initramfs.
Параметры ядра проверяют по /proc/cmdline. На Ubuntu с GRUB сначала испытывают изменение для одного запуска через меню загрузчика, затем редактируют /etc/default/grub и выполняют update-grub. Сохраните рабочий пункт загрузки и консоль VM. Это относится к GRUB: systemd-boot использует другие конфигурационные механизмы. Название параметра и доступность сверяют с документацией своего ядра.
Минимальная привилегия и контроль результата
getcap /путь/к/программе читает файловые capabilities. Выдача CAP_NET_BIND_SERVICE разрешает соответствующую привилегированную операцию, но не изолирует программу. Для службы зачастую понятнее AmbientCapabilities=CAP_NET_BIND_SERVICE вместе с ограниченным CapabilityBoundingSet в unit, чем изменение исполняемого файла через setcap. Не назначайте capability универсальному интерпретатору ради одного сценария. Модель capabilities.
Задание: приложение с лимитом 1024 держит 1010 дескрипторов, после каждого запроса добавляется ещё один. Запишите два независимых результата: подтверждение утечки и временный предел, позволяющий провести диагностику. Объясните, почему изменение fs.file-max, MemoryMax или прав каталога не устраняет причину. Ресурсные ограничения cgroups разобраны в [уроке 27](/lessons/without-university/linux-developer-foundations/linux-developer-27).