cpulimit 不支持按用户限制,仅能通过 PID、程序名或路径限制进程;正确方案是使用 cgroups v2 或 systemd user slice 实现用户级 CPU 配额。

cpulimit 不能直接限制用户,只能限制进程
想用 cpulimit -u username 直接限用户?它根本不支持这个参数。因为 cpulimit 是基于 ptrace 的运行时干预工具,只认 -p(PID)、-e(程序名)、-P(绝对路径)——没有用户、UID 或 session 抽象层。你写 cpulimit -e python3 -l 30,它只会匹配 ps 输出里第一个 python3 进程,不管属主是谁,也不区分 root 还是普通用户。
常见错误现象:
- 普通用户执行 cpulimit -u www-data 报错 “unrecognized option”
- root 执行类似命令也失败,不是权限问题,是语法根本不存在
- 误以为 pgrep -u www-data | xargs cpulimit -e ... 能生效,其实 -e 和管道不兼容,必须用 -p
- 真正可用的间接方式:先用
pgrep -u username拿 PID 列表,再逐个喂给cpulimit -p - 加
-z参数让每个cpulimit实例在对应进程退出后自动终止,避免残留进程堆积 - 过滤掉 shell、sshd 等基础进程:用
pgrep -u username -f 'python\|node\|ffmpeg',别无脑扫全量
长期稳定限制用户 CPU,必须用 cgroups v2
如果你要的是开机即生效、内核级、不依赖外部进程的用户级 CPU 配额,cpulimit 就是错配工具。正确路径是 cgroups v2 + /sys/fs/cgroup 下的 cpu.max 文件。
关键操作步骤:
- 确保系统启用 cgroups v2(现代发行版默认开启,检查 mount | grep cgroup2)
- 创建用户专属子组:sudo mkdir /sys/fs/cgroup/user-www
- 启用 cpu 控制器:echo "+cpu" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
- 设定带宽上限:比如限制为 0.5 核 = echo "50000 100000" | sudo tee /sys/fs/cgroup/user-www/cpu.max
-
cpu.max是绝对微秒值,不是百分比,也不随物理核心数缩放:写"50000 100000"就是每 100ms 最多跑 50ms,无论机器是 2 核还是 64 核 - 把用户所有进程塞进去:
pgrep -u www-data | sudo tee -a /sys/fs/cgroup/user-www/cgroup.procs(注意是cgroup.procs,不是tasks) - systemd 用户会话可自动绑定到
/sys/fs/cgroup/user.slice/user-<uid>.slice</uid>,但需启用 linger:sudo loginctl enable-linger www-data
systemd user slice 是最省心的生产方案
如果你的服务由 systemd --user 管理(比如用户级 nginx、redis-server),优先走 systemctl --user set-property,不用手搓 cgroup 路径。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
前提条件:
- systemd ≥ v240
- 用户已启用 linger:sudo loginctl enable-linger username
- 用户 session 正在运行(登录过或 systemd-run --scope 触发过)
- 限制整个用户会话:
systemctl --user set-property user.slice CPUQuota=40% - 限制某个用户服务:
systemctl --user set-property myapp.service CPUQuota=75% - 效果实时生效,无需重启服务,且重启后自动恢复
- 背后仍是 cgroups v2,但 systemd 封装了路径、控制器启用、进程迁移等细节,出错概率远低于手动操作
别踩这些坑
实际部署时最容易翻车的地方不在命令本身,而在上下文假设:
-
cpulimit -l 100在双核机器上 ≠ 占满整机 100%,它只占满单核(即整机 50%),要占满得设-l 200——但这是抖动式软限,不准也不稳 - cgroups v2 的
cpu.max写入后,如果目标进程已存在,必须显式echo PID > cgroup.procs才能生效;新建进程默认不属于任何用户 cgroup,除非你配置了/etc/systemd/logind.conf中的UserTasksMax和RuntimeDirectoryMode - systemd user slice 只管该用户通过
systemd --user启动的进程,SSH 直连跑的bash或python不会自动纳入,得靠loginctl attach或改写启动方式
真正按用户维度做资源隔离,从来就不是一条命令的事。cgroups v2 路径、systemd 用户会话状态、进程归属关系——三者缺一不可。漏掉任意一个,看起来命令执行成功了,实际流量照样冲破限制。

















