别对已运行的composer进程临时塞入cgroup——子进程会逃逸导致限制失效;必须从启动时用systemd-run --scope绑定cgroup v2限制,如systemd-run --scope -p cpuquota=30% -p memorymax=800m -- composer install,且需验证mount | grep cgroup2确保启用v2。

直接结论:别对已运行的 composer 进程临时塞进 cgroup —— 它 fork 出的子进程(如 git、curl、解压进程)会逃逸,限制基本失效。必须从启动时就约束,且推荐用 systemd-run --scope,不是手建目录。
确认系统用的是 cgroup v2 而不是 v1
Composer 同步(如 composer install 或 composer update)本质是一连串短生命周期子进程:git clone、tar 解包、PHP 解析、JSON 读写。v1 的多层级结构会让这些子进程轻易掉出控制组;v2 统一层级 + 自动进程迁移才是可靠基础。
执行以下命令验证:
mount | grep cgroup2
正确输出应类似:
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,seclabel,relatime,nsdelegate)
如果只看到 cgroup(无 2)或输出为空,说明系统仍在用 v1 或未启用 v2 —— 此时强行配置容易失败,建议先升级内核或切换发行版(如 Ubuntu 22.04+、Fedora 31+ 默认启用 v2)。
用 systemd-run --scope 启动带资源限制的 Composer 命令
这是最简、最稳的方式。它自动处理控制器启用、子树委派、进程继承和退出清理,避免手动操作中常见的 cgroup.subtree_control 忘写、cgroup.procs 写错、残留目录等问题。
例如,限制一次 composer install 最多用 1 核 CPU 的 30%、内存不超过 800MB:
systemd-run --scope -p CPUQuota=30% -p MemoryMax=800M -- composer install
关键点:
-
CPUQuota=30%对应 v2 的cpu.max,表示每 100ms 周期内最多用 30ms CPU 时间 -
MemoryMax=800M对应memory.max,但注意:它不杀进程,只让后续malloc或mmap失败;若要严格防 OOM,加-p MemorySwapMax=0 -
--scope表示临时作用域,命令结束即销毁整个 cgroup,不留垃圾 - 不要加
sudo—— 普通用户只要没被 systemd 策略禁止,就能用--scope
为什么不能用 cgexec 或手写 cgroup.procs
常见错误是这样操作:
mkdir /sys/fs/cgroup/composer-limited<br>echo '+cpu +memory' > /sys/fs/cgroup/composer-limited/cgroup.subtree_control<br>echo '30000 100000' > /sys/fs/cgroup/composer-limited/cpu.max<br>echo 800M > /sys/fs/cgroup/composer-limited/memory.max<br>echo $PID > /sys/fs/cgroup/composer-limited/cgroup.procs
问题在于:
-
composer启动后立刻fork()出git、curl等子进程,而cgroup.procs只写入主进程 PID,子进程默认进入父 cgroup(通常是 root),不受限 - v2 中
cgroup.procs不自动迁移子进程,除非该 cgroup 启用了 delegation(Delegate=yes),而手建目录默认不启用 -
cgexec -g cpu,memory:composer-limited composer install在 v2 下已不推荐,部分发行版甚至不带cgexec,且它仍依赖手动挂载和控制器启用,容错率低
监控是否真生效:别只看 top,用 pidstat 看实际归属
top 或 htop 显示的是进程视角的 CPU%,无法反映 cgroup 限额是否起作用。真正要看的是该进程是否被 throttled(节流)或内存分配是否受阻。
安装并运行:
apt install sysstat -y # Ubuntu/Debian<br>yum install sysstat -y # CentOS/RHEL<br>pidstat -u -G "composer" 1 5
如果看到 %usr 长期卡在 30% 左右(而非飙升到 100%),且 UID 列显示为当前用户,说明 CPU 限额已生效;再配合:
cat /sys/fs/cgroup/composer-limited/cpu.stat
查看 nr_throttled 和 throttled_time 是否增长 —— 增长即表示确实被内核主动限频了。
最后提醒一句:Composer 同步本身 I/O 密集,cgroup v2 目前对 io 控制器的支持仍不如 CPU 和 memory 成熟,若磁盘被打满,优先考虑用 ionice 或调整文件系统调度器,而不是强依赖 io.max。











