С чего начать Первые шаги трек · 15 ступеней
Linux Labs

ulimit и лимиты процесса: открытые файлы, процессы, core

7 мин Ubuntu 24.04 · bash 5.2 · systemd 255

Лимиты ресурсов процесса — открытые файлы, процессы, core: ulimit, /proc//limits и LimitNOFILE службы.

Шпаргалка

7 команд Версия для печати
  • ulimit -a все лимиты оболочки
  • ulimit -Sn; ulimit -Hn мягкий и жёсткий лимит файлов
  • ulimit -Sn 4096 поднять только мягкий, до жёсткого
  • cat /proc/1234/limits лимиты работающего процесса
  • ls /proc/1234/fd | wc -l сколько файлов он держит сейчас
  • sudo prlimit --pid 1234 --nofile=4096:8192 поменять на лету
  • systemctl show app -p LimitNOFILE -p LimitNOFILESoft

Обзор

Ядро ограничивает каждый процесс: сколько файлов он держит открытыми, сколько процессов запускает его пользователь, какой core-файл записать при падении. Лимиты наследуются: потомок получает лимиты родителя. Чаще всего упираются в лимит открытых файлов. Сокет соединения — тоже открытый файл: сервер с тысячей клиентов держит тысячу дескрипторов.

Мягкий и жёсткий

У каждого лимита два значения. Мягкий (soft) действует сейчас. Жёсткий (hard) — потолок: до него процесс сам поднимает мягкий. Опустить можно оба, поднять жёсткий — только root, и не выше fs.nr_open (1048576 на машине тренажёра).

text
student@ubuntu:~$ ulimit -Sn; ulimit -Hn
1024
1048576
student@ubuntu:~$ ulimit -n 4096; ulimit -Sn; ulimit -Hn
4096
4096
student@ubuntu:~$ ulimit -Hn 8192
-bash: ulimit: open files: cannot modify limit: Operation not permitted

ulimit -n без -S и -H в bash меняет оба значения сразу. Жёсткий опустился до 4096, и поднять его в этой оболочке student уже не может. Мягкий отдельно — ulimit -Sn 2048.

Какие лимиты бывают

ulimit limits.conf systemd Что На машине
-n nofile LimitNOFILE открытые файлы и сокеты 1024
-u nproc LimitNPROC процессы пользователя 1679
-c core LimitCORE размер core-файла 0
-s stack LimitSTACK стек, КиБ 8192
-l memlock LimitMEMLOCK закреплённая память, КиБ 65536
-f fsize LimitFSIZE размер файла unlimited

Столбец «На машине» — мягкие значения из ulimit -a у student.

Лимиты процесса: /proc/<PID>/limits

ulimit показывает лимиты твоей оболочки. Лимиты другого процесса — в файле /proc/<PID>/limits, его может прочитать любой пользователь. У службы ssh:

Limit Soft Limit Hard Limit Units
Max open files 1024 524288 files

prlimit меняет лимиты работающего процесса без перезапуска:

text
student@ubuntu:~$ s=$(systemctl show -p MainPID --value ssh)
student@ubuntu:~$ sudo prlimit --pid $s --nofile
RESOURCE DESCRIPTION              SOFT   HARD UNITS
NOFILE   max number of open files 1024 524288 files
student@ubuntu:~$ sudo prlimit --pid $s --nofile=4096:8192

Это действует до перезапуска процесса. Постоянное значение для службы — в её юните.

Лимит службы: LimitNOFILE

Службы systemd получают лимиты от systemd: ulimit в терминале и /etc/security/limits.conf на них не действуют. По умолчанию — мягкий 1024, жёсткий 524288:

bash
systemctl show -p DefaultLimitNOFILE -p DefaultLimitNOFILESoft
text
DefaultLimitNOFILE=524288
DefaultLimitNOFILESoft=1024

Свой лимит кладут в drop-in:

bash
sudo mkdir -p /etc/systemd/system/ssh.service.d
printf '[Service]\nLimitNOFILE=65536\n' \
  | sudo tee /etc/systemd/system/ssh.service.d/limits.conf
sudo systemctl daemon-reload
sudo systemctl restart ssh
grep 'open files' /proc/$(systemctl show -p MainPID --value ssh)/limits

LimitNOFILE=65536 ставит оба значения, разные — LimitNOFILE=4096:65536 (мягкий:жёсткий). После daemon-reload systemctl show уже печатает 65536, а работающий процесс живёт со старыми лимитами — до restart:

Момент systemctl show /proc/<PID>/limits
после daemon-reload 65536 старые значения
после restart 65536 65536 и 65536

limits.conf: лимиты при входе

/etc/security/limits.conf и файлы /etc/security/limits.d/*.conf читает модуль PAM при входе — ssh, login, su -l. Так задают лимиты сеансам пользователей. На машине тренажёра в файле только комментарии.

text
deploy  soft  nofile  65535
deploy  hard  nofile  65535

Рецепты

2

Сколько файлов открыто и сколько можно

bash
pid=$(systemctl show -p MainPID --value app)
sudo ls /proc/$pid/fd | wc -l
grep 'open files' /proc/$pid/limits

Число дескрипторов близко к мягкому лимиту — служба вот-вот получит Too many open files. Растёт и не падает — служба не закрывает файлы (утечка); кто открыт, покажет lsof -p <PID>.

Поднять лимит в своей оболочке

bash
ulimit -Hn                # потолок
ulimit -Sn 65536          # до потолка можно без root

Действует на эту оболочку и всё, что из неё запущено.

Неполадки

5

Too many open files

Процесс упёрся в мягкий лимит nofile (код ошибки EMFILE, номер 24):

text
student@ubuntu:~$ (ulimit -n 16; python3 -c \
  'f=[open("/etc/hostname") for i in range(20)]')
OSError: [Errno 24] Too many open files: '/etc/hostname'

Проверь Max open files в /proc/<PID>/limits и число файлов в /proc/<PID>/fd. Служба — подними LimitNOFILE drop-in'ом и перезапусти её. Число дескрипторов растёт без нагрузки — ищи утечку в приложении.

cannot modify limit: Operation not permitted

Мягкий поднимают выше жёсткого или жёсткий выше текущего без root. root получит то же выше fs.nr_open. Проверь ulimit -Hn; в своей оболочке жёсткий, опущенный ulimit -n, не вернуть — открой новую.

Поднял в limits.conf, а службе не помогло

limits.conf действует на вход пользователей через PAM. Службе нужен LimitNOFILE= в юните или drop-in'е (см. ulimit).

systemctl show показывает новый лимит, а служба падает по-старому

После daemon-reload служба не перезапущена: лимиты процесс получает при запуске. sudo systemctl restart <служба> и проверь /proc/<PID>/limits.

fork: retry: Resource temporarily unavailable

Пользователь упёрся в лимит процессов nproc (ulimit -u). Часто это программа, которая плодит процессы в цикле. Найди её (ps -u <user> | wc -l), останови; для службы — LimitNPROC= или TasksMax=.

Опасно

1

ulimit -n в рабочей оболочке

ulimit -n 4096 опускает и жёсткий лимит. Обратно его поднимет только root — обычному пользователю поможет лишь новая оболочка. Для пробы запускай ulimit в подоболочке: (ulimit -n 16; команда).

См. также

  • proc-filesystem — /proc/<PID>/limits и /proc/<PID>/fd.
  • lsof — какие файлы держит процесс.
  • systemd — юниты и drop-in.
  • sysctl — fs.nr_open и другие параметры ядра.
  • cgroups-namespaces — TasksMax и другие лимиты группы.
  • users-groups — пользователи и группы для limits.conf.
Загрузка…