根本原因是ulimit -n仅临时修改当前shell软限制,而硬限制未同步提升、宿主机/dockerd/systemd/应用层四层限制未协同调优,导致文件描述符池实际仍被卡在低值。

为什么 ulimit -n 65536 还是报 Too many open files
根本原因不是 Composer 写得差,而是它在解压 .tar.gz、扫描 vendor/ 下成千上万个文件、并行下载时,会**瞬间爆发式打开大量文件描述符**——不是匀速开,是毫秒级集中开。而 ulimit -n 只改当前 shell 的软限制,若硬限制(ulimit -Hn)仍是 4096,软限会被静默截断;更麻烦的是,Docker 容器、systemd 服务、IDE 后台进程都在共享同一套句柄池,你只调 Composer 所在终端,等于只拧松一个螺丝。
验证是否真被文件句柄卡住
别猜,分两步实测:
- 运行
ulimit -Sn和ulimit -Hn,两个值都必须 ≥ 65536 才算真正生效 - 进目标环境(比如容器里),执行
ls /proc/1/fd | wc -l,输出接近或等于ulimit -n值,就是它了 - 顺手查全局上限:
cat /proc/sys/fs/file-max,若低于 200000,单调进程限制也白搭
Docker Compose 里 ulimits 配置怎么写才有效
常见错误是把 ulimits 嵌套在 resources 下,或者只设 soft 不设 hard,结果配置根本不加载。正确写法必须与 image、ports 同级,且 hard ≥ soft:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
services:
app:
image: php:8.3
ulimits:
nofile:
soft: 65536
hard: 65536
别忘了:宿主机上的 dockerd 进程本身也受 systemd 限制,需同步改 /etc/docker/daemon.json 加 default-ulimits,否则容器继承的是 dockerd 的低值。
systemd 服务和 macOS launchd 怎么绕过 limits.conf 失效陷阱
/etc/security/limits.conf 对 systemd 服务完全无效,对 macOS 的 launchd 也基本没用——它们不走 PAM 流程。必须单独配:
- systemd:在 service 文件里加
LimitNOFILE=65536,Nginx、PHP-FPM、自建部署脚本全都要加 - macOS:不能靠
ulimit命令,得配 per-userlaunchd.plist或系统级/etc/launchd.conf - 检查 PAM 是否加载:确认
/etc/pam.d/common-session(Debian/Ubuntu)或/etc/pam.d/system-auth(RHEL/CentOS)含未注释的session required pam_limits.so
改完 limits.conf 必须重登系统(SSH 重连或 GUI 登出重进),source ~/.zshrc 没用。










