
Итак, у меня 4 ГБ ОЗУ + 4 ГБ подкачки. Я хочу создать пользователя с ограниченной оперативной памятью и подкачкой: 3 ГБ ОЗУ и 1 ГБ подкачки. Возможно ли это? Возможно ли запускать приложения с ограниченной оперативной памятью и доступной для них подкачкой, не создавая отдельного пользователя (и не устанавливая никаких специальных приложений — имея только конфигурацию сервера Debian/CentOS по умолчанию и не используя sudo)?
Обновлять:
Итак, я открыл терминал и ввел в негоulimitкоманда: ulimit -v 1000000
которая должна быть как 976,6Mb
ограничение. Затем я вызвал ulimit -a
и увидел, что ограничение "включено". Затем я запустил какой-то скрипт bash, который компилирует и запускает мое приложение в nohup
,длинный nohup ./cloud-updater-linux.sh >& /dev/null &
... но через некоторое время я увидел:
(что было бы нормально, если бы не было ограничений — он загрузил какую-то большую библиотеку и начал ее компилировать.)
Но я думал, что применил ограничения к оболочке и всем процессам, запущенным с/из нее с помощью ulimit -v 1000000
? В чем я ошибся? Как сделать так, чтобы терминал и все подпроцессы, которые он запускает, были ограничены по использованию оперативной памяти?
решение1
ulimit
создано для этого. Вы можете установить значения по умолчанию для ulimit
каждого пользователя или для каждой группы в
/etc/security/limits.conf
ulimit -v KBYTES
устанавливает максимальный размер виртуальной памяти. Я не думаю, что можно задать максимальный размер подкачки. Это просто ограничение на объем виртуальной памяти, которую может использовать пользователь.
Таким образом, у вас limits.conf
будет строка (максимум 4G
памяти)
luser hard as 4000000
ОБНОВЛЕНИЕ - CGroups
Ограничения, налагаемые ulimit
и limits.conf
на процесс. Я определенно не был ясен по этому поводу.
Если вы хотите ограничить общий объем памяти, используемый пользователем (о чем вы и просили). Вы хотите использоватьcgroups.
В /etc/cgconfig.conf
:
group memlimit {
memory {
memory.limit_in_bytes = 4294967296;
}
}
Это создает cgroup
файл с максимальным ограничением памяти в 4 ГБ.
В /etc/cgrules.conf
:
luser memory memlimit/
Это приведет к тому, что все запущенные процессы luser
будут выполняться внутри memlimit
cgroups, созданных в cgconfig.conf
.
решение2
cgroups
являются правильным способом сделать это, как было указано в других ответах. К сожалению, идеального решения этой проблемы не существует, о чем мы поговорим ниже. Существует множество различных способов установить ограничения на использование памяти cgroup. То, как можно сделать сеанс входа пользователя автоматически частью cgroup, варьируется от системы к системе. Красная Шапкаимеет некоторые инструменты, и такжесистемд.
memory.memsw.limit_in_bytes
и memory.limit_in_bytes
установить ограничения, включая и не включая swap, соответственно. Недостатком memory.limit_in_bytes
является то, что он подсчитывает файлы, кэшированные ядром от имени процессов в cgroup, по сравнению с квотой группы. Меньше кэширования означает больше доступа к диску, поэтому вы потенциально теряете некоторую производительность, если в противном случае система имела бы некоторую доступную память.
С другой стороны, memory.soft_limit_in_bytes
позволяет cgroup выходить за пределы квоты, но если вызывается ядро OOM killer, то те cgroup, которые превысили свои квоты, будут убиты первыми, что логично. Однако недостатком этого является то, что существуют ситуации, когда некоторая память нужна немедленно, и у OOM killer нет времени искать процессы для уничтожения, в этом случае что-то может выйти из строя до того, как будут убиты процессы пользователя, превысившие квоту.
ulimit
, однако, совершенно не подходит для этого. ulimit накладывает ограничения на использование виртуальной памяти, что почти наверняка не то, что вам нужно. Многие реальные приложения используют гораздо больше виртуальной памяти, чем физической. Большинство сред выполнения со сборкой мусора (Java, Go) работают таким образом, чтобы избежать фрагментации. Тривиальная программа "hello world" на языке C, скомпилированная с помощью address sanitizer, может использовать 20 ТБ виртуальной памяти. Распределители, которые не полагаются на sbrk
, такие какджемаллок(который является распределителем по умолчанию для Rust) илиtcmalloc, также будут использовать виртуальную память, существенно превышающую их физическое использование. Для эффективности многие инструменты будут использовать mmap-файлы, что увеличивает виртуальное использование, но не обязательно физическое использование. Все мои процессы Chrome используют 2 ТБ виртуальной памяти каждый. У меня ноутбук с 8 ГБ физической памяти. Любой способ, которым кто-либо попытается настроить квоты виртуальной памяти здесь, либо сломает Chrome, либо заставит Chrome отключить некоторые функции безопасности, которые полагаются на выделение (но не использование) больших объемов виртуальной памяти, либо будет совершенно неэффективен в предотвращении злоупотребления системой пользователем.
решение3
Вы не можете ограничить использование памяти на уровне пользователя, ulimit может сделать это, но для одного процесса.
Даже при использовании ограничений на пользователя в /etc/security/limits.conf
, пользователь может использовать всю память, запустив несколько процессов.
Если вы действительно хотите ограничить ресурсы, вам нужно использовать инструмент управления ресурсами, напримерrcapdиспользуется проектами и зонами под управлением Solaris.
Похоже, в Linux есть нечто, предоставляющее похожие функции, которые вы можете изучить:cgroups.
решение4
В системе с systemd (например, Ubuntu 22.04, которую я использую) самый простой способ ограничить ЦП/память — это использовать файлы конфигурации systemd cgroups, например, для ограничения 4 ГБ ОЗУ и 2 потоков:
nano /etc/systemd/system/user-.slice.d/50-memory.conf
И запишите в этом файле:
[Slice]
MemoryMax=4G
CPUQuota=200%
(запустите, systemctl daemon-reload
чтобы применить)
Это относится ко всем пользователям, но вы можете переопределить действия отдельных пользователей./etc/systemd/system/user-[uid].slice.d/50-memory.conf
(Я думаю, что имя файла конфигурации не имеет значения, но я не уверен)