Ulimit (limits.conf) настройка частых проблем в Linux

ulimit - ограничения текущего процесса, например количество одновременно открытых файлов. Справка man limits.conf. Конфигурационный файл находится /etc/security/limits.conf.

Установка лимитов с помощью ulimit может предотвратить катастрофу в ваших системах Linux, но вам нужно предвидеть, где ограничения будут иметь смысл, а где они вызовут проблемы.

Чтобы увидеть ограничения, связанные с вашим логином, используйте команду ulimit -a. Если вы используете учетную запись обычного пользователя, вы, скорее всего, увидите что-то вроде этого:

~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7728
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7728
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Изменять лимиты вы можете в конфигурационном файле, обычно /etc/security/limits.conf, или при помощи командной строки. Помните что при изменении лимитов через командную строку, ваши изменения не сохранятся после перезагрузки ОС. Например для изменения максимального количества пользовательских процессов (max user processes) используйте ключ u (из листинга вывода команды ulimit -a):

ulimit -u 8000

В limits.conf для каждого пользователя или группы можно задать ограничения. Каждое ограничение задается в отдельной строке. Например для группы developers настроим ограничения пределов открытия файлов, где hard жестко задали количество, а при достижении нижнего предела значения soft пользователи будут получать предупреждения):

@developers        soft    nofile         2048
@developers        hard    nofile         8192

Читайте также: ProcFS файловая система для процессов (/proc)

Soft limit (мягкий лимит) обычно устанавливается на более низком уровне и действует как предупреждение для пользователя. Это не окончательный предел, но при его достижении система может предупредить пользователя, что ресурсы приближаются к исчерпанию. Рекомендуемое значение для soft nofile может варьироваться, но часто устанавливается в диапазоне от 1024 до 4096.

Hard limit (жесткий лимит) устанавливает абсолютный максимум, который не может быть превышен ни при каких обстоятельствах. Этот лимит служит для защиты системы от перегрузки. Рекомендуемое значение для hard nofile обычно значительно выше и может быть установлено в пределах от 4096 до 65535, в зависимости от требований системы и приложений.

Например, строка в limits.conf может выглядеть так:

* soft nofile 4096
* hard nofile 65535

Это означает, что для всех пользователей мягкий лимит на количество открытых файлов установлен на 4096, а жесткий лимит - на 65535.

Ошибка «Too many open files» (Слишком много открытых файлов) означает, что сервер исчерпывает ресурс на максимальный предел открытых файлов (max open file limit).

Нужно увеличить ограничение на количество одновременно открытых файлов в файле limits.conf. Для начала проверим какой предел установлен в ОС, для этого используем данные из файловой системы ProcFS. И проверим параметр задающие число одновременно открытых файлов

# cat /proc/sys/fs/file-max
348651

Зададим для пользователя asterisk

# nano /etc/security/limits.conf
...
asterisk         soft    nofile           65535
asterisk         hard    nofile           65535
...

Проверим ulimit -a

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65536
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

В основном при работе в системе UNIX мы считаем, что ее ресурсы безграничны. Например, мы не заботимся о том, что созданный файл получится "слишком большим", а это не так уж редко в персональных компьютерах на гибких дисках. Если же мы занимаемся сопровождением и администрированием системы UNIX, то мы должны быть готовы иметь дело с ситуациями, когда превышаются различные предельные значения системы. Всегда лучше исследовать эти вопросы заранее в некритичных ситуациях, поэтому давайте рассмотрим пределы размеров файлов и их смысл.

Некоторые параметры "зашиты" в ядро системы при ее генерации. Одним из таких значений является максимальный размер файла. Он определяет наибольшее число блоков, которые может занимать файл. Этот параметр тесно связан с принятым в UNIX методом использования индексных дескрипторов файла (inodes). Это наборы указателей, среди которых первые десять указывают на блоки данных, следующий указывает на другую таблицу, следующий - на таблицу, указывающую на таблицу и т.д.

Имеется еще одно ограничение размера файла, которое определено для каждого пользователя во время работы в системе - число ulimit (user limit - пользовательский предел). Это значение устанавливается в момент вашей регистрации в системе и представляет собой число блоков по 512 байт, которые вы можете записать в любой заданный файл. В shell'е имеется команда ulimit, которая при ее вызове без аргументов выводит это число. Эта же команда позволяет вам уменьшить ваше значение ulimit. Только суперпользователь (root) может УВЕЛИЧИТЬ значения ulimit.

Побочным эффектом уменьшения значения ulimit является то, что вы не можете снова увеличить его до регистрационного значения. Значение ulimit остается таким же на все время работы вашего shell, поэтому для восстановления регистрационного значения вам необходимо выйти из системы, а затем снова зарегистрироваться.

Еще одним интересным моментом является то, что если вы установите ваше значение ulimit равным 0, вы не сможете создать никакие файлы! Максимально допустимым размером файла в данном случае является нулевой, поэтому никакой файл не может быть создан. Это представляется достаточно резонным, однако существуют такие ситуации, когда файл нулевого размера МОЖЕТ существовать. Опять же, для восстановления вашего обычного значения ulimit необходимо выйти из системы, а затем снова зарегистрироваться.

Как отмечалось ранее, увеличить значение ulimit может только суперпользователь. Эта процедура довольно проста. Сначала нужно увеличить значение ulimit командой ulimit, а затем запустить shell. Этот новый shell имеет новое значение ulimit. Если мы хотим, чтобы система загружалась с shell, имеющим большее значение ulimit, мы можем установить программу в inittab (таблице инициализации системы), чтобы эта операция выполнялась автоматически.

В Nginx файловые дескрипторы необходимы для каждого соединения с клиентом, для возврата статического файла из кэша. Количество потребных дескрипторов может быстро возрастать. Однако общее количество дескрипторов ограничено операционной системой. Ограничение на количество одновременно открытых сокетов: Обычно, большая часть nix систем ограничивает количество сокетов до 1024.

Предполагаем что процессы сервера Nginx запущены от пользователя nginx. Для удобства просмотра ограничений операционной системы для пользователя nginx, залогинемся под ним. Стандартный запуска su не поможет (получим ошибку: This account is currently not available), так пользователь системный, нужно использовать ключи:

# su -l nginx -s /bin/bash
$ whoami
nginx

Или просто запустим команду от имени nginx:

# su nginx -s /bin/bash -c 'ulimit  -a'

Давайте соберем текущие значения.

Текущий лимит (Soft limit) открытых файлов на процесс для текущего пользователя

su nginx -s /bin/bash -c 'ulimit -Sn'
1024

Максимальный лимит (Hard limit) открытых файлов на процесс для текущего пользователя

su nginx -s /bin/bash -c 'ulimit -Hn'
4096

Посчитать количество открытых файлов всеми процессами

# lsof | wc -l
9973

Посчитать количество открытых файлов всеми процессами, по данным ядра Линукс. Мы увидим 3 цифры (число открытых в данный момент файлов; число открытых, но не используемых файлов; максимальное число открытых файлов).

# cat /proc/sys/fs/file-nr
2112    0       94547

Максимальный лимит открытых файлов для всей системы

# cat /proc/sys/fs/file-max
94547

Исходя из полученных цифр выше, минимально рекомендуемые цифры для Nginx ulimit, получились такие. Добавим их в файл /etc/security/limits.conf

nginx soft nofile 4096
nginx hard nofile 10240

Теперь меняем лимиты в nginx, для этого в файле /etc/nginx/nginx.conf в самом начале, примерно после строк

user nginx;

пишем
worker_rlimit_nofile 10240;

Директива worker_rlimit_nofile изменяет ограничение на количество файлов, открытых в рабочем процессе.

Не ставьте число лимитов больше 65535. В случае входящих соединений, очевидного лимита в 65535 соединений нет, скорей всего вы упретесь в лимит на файловые дескрипторы (сокеты), для каждого соединения нужен сокет. При этом лимиты могут быть на уровне пользовательских лимитов (и надо учесть для сервисов запускаемых через systemd действуют отдельные лимиты, а не те, которые указываются в limits.conf). Обычно по умолчанию лимиты дескрипторов в районе 1024-4096, существенно ниже 65535. Для очень большого количества сокетов необходимо будет так же менять sysctl на максимальное число открытых файлов, а возможно и пересобирать ядро, чтобы обойти заложенные верхние ограничения.

PQ VPS сервера в 28+ странах.