Настраиваемые лимиты в Linux
Введение
В Linux ограничения можно задавать на нескольких уровнях. Одни лимиты действуют для всей системы, другие — для пользователей или отдельных служб SystemD. В этой статье мы рассмотрим три конфига для разных подсистем Linux, с помощью которых можно задать некоторые ограничения для системы, для процессов, для пользователя или служб:
- Лимиты, накладываемые ядром -
sysctl.conf. - Лимиты, накладываемые подсистемой PAM -
limits.conf. - Лимиты, накладываемые системой инициализации SystemD -
system.conf.
Несмотря на похожее назначение, эти механизмы работают независимо друг от друга и применяются на разных этапах работы системы.
Лимиты, накладываемые sysctl.conf
Каждый открытый файл занимает файловый дескриптор. Информация об используемых файловых дескрипторах и их лимите хранится в файле /proc/sys/fs/file-nr:
$ cat /proc/sys/fs/file-nr
1120 0 9223372036854775807
В выводе мы видим 3 числа:
- Число выделенных файловых дескрипторов (
1120) - обычно соответствует числу открытых файлов. - Число выделенных, но не используемых файловых дескрипторов (
0). Ядро версии выше чем Linux 2.6 всегда показывает 0, потому что количество выделенных файловых дескрипторов точно соответствует количеству используемых файловых дескрипторов. - Максимальное число файловых дескрипторов (
9223372036854775807) - лимит открытых файлов в системе.
Для того, чтобы задать лимит для всей системы, нужно в файле /etc/sysctl.conf использовать параметр fs.file-max:
$ sudo nano /etc/sysctl.conf
fs.file-max=1000000
Применим изменения и проверим:
$ sudo sysctl -p
$ cat /proc/sys/fs/file-nr
1120 0 1000000
- На практике этот лимит обычно увеличивают, а необходимость уменьшать его возникает крайне редко.
Это был лимит для системы в целом, также можем настроить лимит для каждого процесса. Вначале посмотрим какой лимит стоит по умолчанию. Для этого нужно смотреть файл /proc/sys/fs/nr_open:
$ cat /proc/sys/fs/nr_open
1073741816
- Любой процесс в системе не сможет открыть более 1073741816 файлов.
Чтобы поменять это значение используем файл /etc/sysctl.conf и параметр fs.nr_open:
$ sudo nano /etc/sysctl.conf
fs.nr_open=65536
$ sudo sysctl -p
$ cat /proc/sys/fs/nr_open
65536
Чтобы узнать, сколько сейчас открыто файлов у произвольного процесса, выполните ls /proc/<pid>/fd | wc -l:
$ sudo ls /proc/1068/fd/ | wc -l
11
А для того, чтобы пробежаться по списку процессов определённого пользователя и узнать сколько файлов эти процессы открыли, я написал такой скрипт:
$ nano openfiles-users-procs.sh
#!/bin/bash
case "$1" in
-h)
echo -e "Скрипт покажет открытые файлы для выбранного пользователя.
Опции:
-h показать эту справку.
Примеры выполнения:
./files2.sh <username>
./files2.sh <uid>"
;;
*)
if [[ "$#" -eq 1 ]];
then
id "$1" >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
echo 'Пользователь не найден!'
exit 1
fi
for pid in $(ps -u "$1" -o pid=)
do
open_files=0
while IFS= read -r fd
do
target=$(readlink "$fd" 2>/dev/null)
case "$target" in
socket:*|pipe:*|anon_inode:*|memfd:*|"")
;;
*)
((open_files++))
;;
esac
done < <(find "/proc/$pid/fd" -mindepth 1 -maxdepth 1 2>/dev/null)
echo "Открытых файлов для PID $pid: $open_files"
done
else
echo -e "Забыли указать имя или id пользователя!
Или ввели больше одного параметра.
Для справки выполните $0 -h"
fi
;;
esac
Примечание. Скрипт подсчитывает только открытые файлы и исключает сокеты, каналы (
pipe), анонимные inode (anon_inode) и другие дескрипторы, не связанные с файлами файловой системы.
Выполнять нужно с sudo:
$ sudo ./openfiles-users-procs.sh alex
Открытых файлов для PID 1100: 6
Открытых файлов для PID 1102: 2
Открытых файлов для PID 1125: 10
Открытых файлов для PID 1126: 4
Открытых файлов для PID 1136: 0
- Сложив эти числа мы узнаем, сколько файлов открыто у определённого пользователя.
Лимиты, накладываемые PAM — limits.conf
Подсистема PAM (Pluggable Authentication Modules) отвечает за аутентификацию пользователей. PAM используется большинством служб, выполняющих аутентификацию пользователей (SSH, login, su, sudo и др.). При логине в систему, подсистема PAM может наложить определённые лимиты на сеанс пользователя, и эти лимиты настраиваются с помощью /etc/security/limits.conf. Ограничения задаются следующим образом:
$ sudo nano /etc/security/limits.conf
* soft core 0
root hard core 100000
* hard rss 10000
@student hard nproc 20
@faculty soft nproc 20
@faculty hard nproc 50
ftp hard nproc 0
ftp - chroot /ftp
@student - maxlogins 4
Описание четырёх столбцов:
- Указываем кого нужно ограничить:
- если всех пользователей, пишем звёздочку
*; - если определённого пользователя, пишем имя пользователя (
root); - если группу, пишем имя группы начиная с собачки
@student.
- если всех пользователей, пишем звёздочку
- Дальше задаём тип ограничения:
softилиhard.- Мягкое ограничение. Приложение может приблизиться к мягкому лимиту и, если оно поддерживает обработку соответствующего ограничения, скорректировать своё поведение до достижения жёсткого лимита.
- Жёсткое - запрещающее ограничение.
- Если приложение не реагирует на достижение мягкого лимита, то для него и
softиhardсработают одинаково, то есть не дадут получить запрашиваемый ресурс.
- В третьей колонке указываем параметр ограничения:
- core — максимальный размер файла дампа памяти (KB). Такой дамп создаётся при некорректном завершении процесса. Я об этом писал здесь ;
- nofile — максимальное число открытых файлов;
- rss — максимальный размер потребляемой памяти (КБ);
- nproc — максимальное количество процессов;
- maxlogins — максимальное количество входов в систему одним пользователем;
- maxsyslogins — максимальное количество входов в систему всеми пользователями.
- В последней колонке задаются значения ограничивающего параметра.
Примечание. Параметр
rssсоответствует ограничениюRLIMIT_RSS, однако на современных ядрах Linux он фактически не используется. Начиная с Linux 2.4.30 ядро игнорирует этот лимит, поэтому для ограничения потребления памяти обычно применяют cgroups или параметры SystemD (MemoryMax=). Параметр сохранён вlimits.confглавным образом для совместимости.
Лимиты, накладываемые SystemD — system.conf
В операционных системах с системой инициализации SystemD существует специальный конфиг — /etc/systemd/system.conf. С помощью него можно настроить ограничения по умолчанию для служб. Но также, ограничения можно задавать в самих файлах юнитов, в секции [Service].
Файл
system.conf— это основной конфигурационный файл для SystemD.
Когда вы создаёте свой юнит SystemD типа service, то есть службу, вы можете в секции [Service] задать некоторые ограничения для этой службы. Про такие юниты я писал
здесь
. Или вы можете ограничить все службы указав общее ограничение в файле system.conf. При этом ограничение в самом юните приоритетнее, чем общее ограничение.
Рассмотрим некоторые из ограничений в таблице:
| Параметр в файле system.conf | Параметр в файле юнита | Описание параметра |
|---|---|---|
DefaultLimitCPU=<секунд> | LimitCPU=<секунд> | Ограничение в секундах на количество процессорного времени, которое может потреблять процесс. После достижения лимита процесс получает сигнал SIGXCPU. Если он не завершится самостоятельно, ядро принудительно завершит его. |
DefaultLimitFSIZE=<байт> | LimitFSIZE=<байт> | Максимальный размер файлов, которые может создать процесс. При попытке создать файл большего размера процесс либо завершится, либо обработает ошибку и продолжит работать. |
DefaultLimitCORE=<байт> | LimitCORE=<байт> | Максимальный размер файла дампа в байтах, который процесс может сохранить. При значении 0 файлы дампа не создаются. Когда он не равен нулю, большие дампы усекаются до указанного размера. |
DefaultLimitNOFILE=<число> | LimitNOFILE=<число> | Максимальное число открытых файлов. |
DefaultLimitAS=<байт> | LimitAS=<байт> | Максимальный размер виртуальной памяти процесса (address space). После достижения лимита новые попытки выделить память завершаются ошибкой (ENOMEM), а многие приложения после этого завершают работу. |
DefaultLimitNPROC=<число> | LimitNPROC=<число> | Максимальное число процессов. |
DefaultLimitNICE=<уровень> | LimitNICE=<уровень> | Максимальный уровень NICE |
Если понравилась статья, подпишись на мой канал в VK или Telegram .