linux进程数受ulimit -u、kernel.pid_max、kernel.threads-max三层限制,缺一不可;/etc/security/limits.conf需为root和*分别配置soft/hard nproc;systemd服务须用limitnproc=或defaultlimitnproc=;容器中需单独设置namespace级参数。

Linux最大进程数不是改一个地方就能生效的,它被 ulimit -u、kernel.pid_max、kernel.threads-max 三层卡住,漏掉任意一层,Java 应用照样报 java.lang.OutOfMemoryError: unable to create new native thread,Nginx 也照样拒绝 fork 新 worker。
ulimit -u 改了不生效?因为只作用于当前 shell
运行 ulimit -u 65535 看似改了,但关掉终端就回退,新开终端也不继承——它只影响当前 shell 及其直接子进程。普通用户甚至无法突破 hard nproc 的上限,而这个硬限制默认常是 4096 或更低。
- 临时验证可用:
ulimit -S -u 65535 && ulimit -H -u 65535(需 root) - 普通用户只能调低自己的软限制,不能越过硬限制
- root 用户在某些发行版中会绕过
/etc/security/limits.conf,必须显式配root soft nproc和root hard nproc - SSH 登录后不会自动重载 limits,必须完全登出再登录,
su - $USER也行,但source或systemctl restart sshd都没用
/etc/security/limits.conf 写法常见翻车点
很多人写完 * soft nproc 65535 就以为万事大吉,结果 Java 进程启动时还是只有 4096 个线程可用——因为 * 不匹配 root,也不匹配 systemd 启动的服务进程。
- 要覆盖所有用户(含 root),必须分两行:
root soft nproc 65535和* soft nproc 65535,硬限制同理 -
hard值必须 ≥soft,否则软限制设不上;建议统一设为65535或unlimited(root 可用) - 配置文件必须由 PAM 加载,检查
/etc/pam.d/common-session是否有session required pam_limits.so - 更推荐把规则单独放进
/etc/security/limits.d/20-nproc.conf,避免污染主文件
systemd 服务完全不读 limits.conf
nginx、redis、Java Spring Boot 应用如果用 systemctl start 启动,/etc/security/limits.conf 对它们完全无效。它们只认自己 service 文件里的 LimitNPROC=,或全局的 DefaultLimitNPROC=。
- 单服务配置:编辑
/etc/systemd/system/myservice.service,在[Service]段加LimitNPROC=65535 - 全局生效(慎用):在
/etc/systemd/system.conf中设DefaultLimitNPROC=65535 - 改完必须执行:
sudo systemctl daemon-reload && sudo systemctl restart myservice - 若服务用了
User=appuser,LimitNPROC限制的是该用户,不是 root,别搞混
kernel.pid_max 和 kernel.threads-max 是最终天花板
即使用户级全设成 unlimited,内核仍可能静默拒绝 fork。比如 kernel.threads-max 默认按内存估算,一台 16G 机器可能只有 6 万左右;而 kernel.pid_max 若仍卡在 32768,那再多配置也没意义。
- 查当前值:
cat /proc/sys/kernel/pid_max和cat /proc/sys/kernel/threads-max - 临时调高:
sudo sysctl -w kernel.pid_max=196608,echo 65536 | sudo tee /proc/sys/kernel/threads-max - 永久生效:写入
/etc/sysctl.d/99-pidmax.conf(内容:kernel.pid_max = 196608),再运行sudo sysctl --system - 关键约束:
kernel.threads-max必须 ≤kernel.pid_max,否则写入失败,报Invalid argument
真正容易被忽略的是:容器环境(Docker/Kubernetes)默认继承宿主机的 ulimit -u,但 kernel.pid_max 和 kernel.threads-max 是 namespace 级别的,得进容器里单独调;Kubernetes 还得在 Pod spec 的 securityContext 里显式设 limits.nproc,光改宿主机没用。











