prlimit --rss 不能动态限制进程rss,因linux 2.6.32+内核已忽略rlimit_rss;有效方案是cgroup v2的memorymax或prlimit --as限制虚拟内存。

prlimit --rss 不能动态限制运行中进程的物理内存常驻集合(RSS),这个操作在现代 Linux 内核中基本无效。
原因很明确:RLIMIT_RSS 虽然在 getrlimit/setrlimit 接口中存在,但自 Linux 2.6.32+ 起,内核已完全忽略该限制。官方文档(如 man 2 setrlimit)明确说明:
RLIMIT_RSS: This limit has no effect on Linux.
也就是说,无论你用 prlimit --rss=100M --pid 1234 还是 Python 的 resource.setrlimit(resource.RLIMIT_RSS, ...),系统都不会据此杀进程、触发 OOM 或强制回收内存——它只是“摆设”。
✅ 真正有效的替代方案(按推荐顺序)
使用 cgroup v2(最可靠、生产首选)
适用于 systemd 系统(主流发行版默认):
# 创建一个 memory controller scope(临时限制) sudo systemd-run --scope -p MemoryMax=512M -- /path/to/your/program # 或对已有进程 PID=1234 加入限制(需先创建 cgroup) echo 1234 | sudo tee /sys/fs/cgroup/myapp/cgroup.procs echo 536870912 | sudo tee /sys/fs/cgroup/myapp/memory.max # 512MB
✅ 优势:精确控制 RSS + 缓存页,OOM killer 可触发,支持统计
/sys/fs/cgroup/myapp/memory.current
⚠️ 注意:需启用cgroup_enable=memory swapaccount=1内核启动参数(多数云主机已默认开启)
使用 prlimit --as 限制虚拟地址空间(间接控 RSS)
虽然不等于 RSS,但能防止大量 mmap/brk 分配,从而抑制 RSS 增长:
prlimit --as=1G --pid 1234
✅ 有效:
RLIMIT_AS在所有内核版本均受支持,超限会返回ENOMEM
? 提示:Java/Python 等运行时可能预分配大块虚拟内存,此法比--rss更实际
启动前设限(适合可重启服务)
# 临时会话级限制(子进程继承) ulimit -v 1048576 # 1GB virtual memory ./myapp # 或用 prlimit 启动新进程 prlimit --as=1G -- /usr/bin/java -jar app.jar
❌ 不要再试的常见误区
-
prlimit --rss=500M --pid 1234→ 无任何效果,/proc/1234/limits显示值会变,但内核不执行 -
resource.setrlimit(resource.RLIMIT_RSS, (x,x))in Python → 同样被忽略,且可能抛OSError: Invalid argument(取决于内核版本) - 依赖
top或ps的RES字段做“是否超限”判断 → 它只是快照,非硬性拦截机制
快速验证当前进程真实内存限制方式
# 查看进程实际生效的限制(注意 RSS 行是否标为 "unlimited" 或数值,但别信它) cat /proc/1234/limits | grep -i "resident\|as" # 查看 cgroup 内存控制器是否启用及当前用量 cat /proc/1234/cgroup | grep memory [ -f /sys/fs/cgroup/memory/$(cat /proc/1234/cgroup | cut -d: -f3 | cut -d/ -f2)/memory.current ] && \ cat /sys/fs/cgroup/memory/*/memory.current 2>/dev/null | head -1
真正起作用的永远是 MemoryMax(cgroup v2)或 RLIMIT_AS(ulimit/prlimit),不是 RSS。











