在Linux上限制进程的内存和CPU使用

8

我知道我们可以使用nice命令来调整调度优先级。

然而,手册并没有说明它是否会限制CPU和内存,还是只限制CPU(无论如何,它都不能用于指定绝对限制)。

在Linux中有没有一种方法可以运行一个进程并将其内存使用限制为“X” MB,将CPU使用限制为“Y” Mhz?


1
限制CPU使用,我发现cpulimit非常好用,例如: http://www.cyberciti.biz/faq/cpu-usage-limiter-for-linux/ - womd
你真的想要将CPU限制在给定的时钟频率下,还是想要限制最大的CPU使用率,并仍然允许CPU时钟由内核自动调整?请注意,CPU不能以低于高优先级任务的时钟频率并行运行低优先级任务。 - Mikko Rantalainen
3个回答

7

您可能需要调查cgroups,以及较旧的(已过时的)ulimit


谢谢。cgroups看起来就是我需要的东西。 - JP19

4

针对Linux的回答:

在历史系统中,运行ulimit -m $LIMIT_IN_KB将是正确的答案。现在您必须使用cgroupscgexecsystemd-run

然而,对于那些仍在转换到systemd的系统,似乎没有任何解决方案不需要为每个希望使用的限制设置预先制作的配置。这是因为这些系统(例如Debian/Ubuntu)仍使用“混合层次cgroups”,而systemd只支持使用更新的“统一层次cgroups”来设置内存限制。如果您的Linux发行版已经运行了使用统一层次cgroups的systemd,则以特定限制运行给定用户模式进程应该像这样工作:

systemd-run --user --pipe -p MemoryMax=42M -p CPUWeight=10 [command-to-run ...]

或者

systemd-run --user --scope -p MemoryMax=42M -p CPUWeight=10 [command-to-run ...]

有关可能的参数,请参见 man systemd.resource-control

如果我理解得正确,设置 CPUWeight 指示内核在 CPU 完全被占用时给予多少 CPU 时间,其默认值为 100。较低的值意味着当多个进程竞争 CPU 时间时,该进程将获得较少的 CPU 时间。如果 CPU 利用率不到 100%,它不会限制 CPU 使用率,这通常是一件好事。如果您真的想强制进程在机器空闲时使用不到一个核心的资源,您可以设置例如 CPUQuota=10%,以强制进程使用高达单个核心的 10% 资源。如果您设置了 CPUQuota=200%,这意味着该进程最多可以平均使用 2 个核心 (但如果没有 CPU 绑定,它也可以在更多的 CPU 上使用一些时间)。

附加信息:

更新(2021 年): 看起来

systemd-run --user --pty -p MemoryMax=42M -p CPUWeight=10 ...

如果您正在运行包含修复错误https://github.com/systemd/systemd/issues/9512systemd版本,则应该可以正常工作——在实践中,您需要在此处列出的修复程序:https://github.com/systemd/systemd/pull/10894

如果您的系统缺少这些修复程序,则使用以下命令:

systemd-run --user --pty -p MemoryMax=42M -p CPUWeight=10 ...

看起来工作正常,但实际上内存限制并没有得到执行。

事实上,似乎 Ubuntu 20.04 LTS 没有包含所需的修复程序。以下操作应该会失败:

$ systemd-run --user --pty -p MemoryMax=42M -p MemorySwapMax=50M -p CPUWeight=10 stress -t 10 --vm-keep --vm-bytes 10m -m 20

因为命令 stress 预计需要略多于 200 MB 的 RAM,但内存限制设置得更低。根据 bug https://github.com/systemd/systemd/issues/10581,Poettering 表示如果发行版使用 cgroupsv2,则这应该可以工作,不管在实践中意味着什么。

我不知道有哪个 distro 正确实现了用户模式下的 cgroup 限制。结果是,您需要 root 来配置这些限制。


对于没有统一层次结构的解决方法,请参见:https://unix.stackexchange.com/q/436791 - Mikko Rantalainen

2
理论上,你应该能够使用 ulimit 来实现这个目的。然而,我个人从来没有成功过。

getrlimit man页说明它只在Linux <2.4.30中生效,即使是那样,也不完善。 - rcoup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接