真正能硬性限制 composer 构建过程总内存用量的只有 linux cgroup(v1 或 v2),因 composer_memory_limit 和 php -d memory_limit 仅约束主 php 进程堆内存,无法管控 git、unzip 等 fork 子进程的 rss 与 mmap 内存,而 cgroup 在内核层对整个进程树实施 memory.max 硬限制,超限即触发 oom killer。

真正能硬性限制 Composer 构建过程总内存用量的,只有 Linux cgroup(v1 或 v2),COMPOSER_MEMORY_LIMIT 和 php -d memory_limit 都无法约束 fork 出的子进程(如 git clone、unzip、插件调用的 PHP 子进程)——这些进程会绕过 PHP 层限制,直接撞上系统级内存墙。
为什么 php -d memory_limit=2G 还会被 OOM Killer 杀掉
cgroup 的内存限制优先级高于 PHP 所有配置。即使你写了 php -d memory_limit=-1,只要容器或宿主机设置了 memory.max(cgroup v2)或 memory.limit_in_bytes(cgroup v1),内核在 fork 子进程时仍按虚拟地址空间总量做判断;一旦累计 VMA 超限(常见于 opcache CLI 启用、大量 zip 解压、插件加载全量 autoloader),进程就会被静默 Killed,日志里只留三个字母,没有 PHP 错误。
-
php -d memory_limit只控制主 PHP 进程堆内存,不控制 mmap 区域、共享内存段、子进程 RSS -
COMPOSER_MEMORY_LIMIT仅影响依赖解析阶段的缓存结构大小,对解包、脚本执行、插件无约束力 - Docker 默认启用 cgroup v2,
--memory=2g实际设的是memory.max,但 Composer 主进程 + 数十个unzip子进程可能合计突破该值
如何用 cgroup v2 精确限制 Composer 构建内存
在支持 cgroup v2 的系统(Linux kernel ≥ 4.15,默认启用)上,必须显式创建 scope 并绑定资源限制,不能依赖 Docker 的 --memory 封装——因为 Docker 会把整个容器进程树塞进一个 cgroup,而 CI 中常需在同一节点跑多个构建任务,需隔离粒度更细。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 手动创建临时 scope:
systemd-run --scope -p MemoryMax=2G -- php -d memory_limit=2G /usr/bin/composer install - 验证是否生效:
cat /proc/$(pgrep -f "composer install")/cgroup应含memory:/system.slice/...scope - 检查当前限制:
cat /sys/fs/cgroup/system.slice/...scope/memory.max(v2)或memory.limit_in_bytes(v1) - 注意:不要用
cgexec(cgroup v1 工具),它在 v2 环境下行为不可靠,且不自动处理子进程继承
CI/CD 中避坑要点(GitHub Actions、GitLab CI)
云 CI 平台多数禁用 systemd 或只提供 cgroup v1 接口,直接用 systemd-run 会失败。此时应降级使用 ulimit -v + cgroup v1 回退策略,但需接受精度损失。
- GitHub Actions:默认无 systemd,改用
docker run --memory=3g --rm -v $(pwd):/app -w /app php:8.3-cli php -d memory_limit=2G composer install,确保--memory值 >php -d值 - GitLab CI(自建 runner):在
config.toml的[runners.docker]段加memory = "3g",同时在before_script中 exportCOMPOSER_MEMORY_LIMIT=2G - 关键动作:运行前先清空缓存
rm -rf ~/.composer/cache/,损坏的repo/缓存会触发异常解包逻辑,额外拉高虚拟内存占用 - 永远禁用
opcache.enable_cli=1:CLI 模式下 opcache 不释放,预分配数 MB 共享内存段,是 cgroup 下最常被忽略的“内存幽灵”
cgroup 级限制不是可选项,而是现代构建环境的事实标准。当你看到 Killed 却查不到 PHP 内存错误,第一反应不该是加 -d 参数,而是检查 /sys/fs/cgroup/ 下的当前限制和进程归属——那才是内存真正被卡死的地方。










