ulimit -u 修改不生效因仅作用于当前shell,系统级需配limits.conf(分root和*两行)、systemd服务需设limitnproc、内核级需调kernel.pid_max。

为什么 ulimit -u 修改后不生效?
直接运行 ulimit -u 65535 只对当前 shell 及其子进程有效,退出或新登录就恢复默认。系统级限制由 PAM 和内核共同控制,光改 shell 限制没用。
- 普通用户受限于
/etc/security/limits.conf中的nproc设置(注意不是nofile) - root 用户默认可能绕过
limits.conf,需检查/etc/security/limits.d/*.conf是否有覆盖规则 - systemd 服务(如 nginx、redis)不读取
limits.conf,必须通过LimitNPROC=在 service 文件中显式配置
/etc/security/limits.conf 的写法陷阱
常见错误是写成 * soft nproc 65535 就以为全局生效——其实 * 不匹配 root,也不匹配 systemd 启动的用户会话。
- 要覆盖所有用户(含 root),推荐分两行:
root soft nproc 65535* soft nproc 65535 - 硬限制(
hard)必须 ≥ 软限制,否则软限制设不上去;建议同步设置:* hard nproc 65535 - 修改后需重新登录(不是
source或重启 sshd),图形界面用户甚至要完全注销会话
systemd 服务的 LimitNPROC 怎么配才可靠?
很多服务(尤其是容器、Java 应用、数据库)跑在 systemd 下,limits.conf 对它们完全无效。
- 编辑服务文件:
sudo systemctl edit nginx,然后写入:[Service] LimitNPROC=65535
- 若服务使用
User=xxx,LimitNPROC作用于该用户,不是 root - 数值设为
infinity风险高,建议设具体值(如65535)并配合TasksMax=使用(systemd 240+ 版本) - 改完必须
sudo systemctl daemon-reload && sudo systemctl restart nginx,reload 不触发重载 limits
内核级限制:kernel.pid_max 容易被忽略
ulimit 和 LimitNPROC 再大,也跨不过内核上限。默认 kernel.pid_max 通常是 32768(32 位)或 4194304(64 位),但某些云主机或容器环境会被压低。
- 临时修改:
sudo sysctl -w kernel.pid_max=65535 - 永久生效:写入
/etc/sysctl.conf或/etc/sysctl.d/99-pidmax.conf,内容为kernel.pid_max = 65535 - 验证是否生效:
cat /proc/sys/kernel/pid_max,不是sysctl kernel.pid_max(后者可能缓存旧值) - 注意:此值必须 ≥ 单个用户最大进程数 × 并发用户数,否则系统会拒绝 fork
实际调优时,kernel.pid_max 和用户级 nproc 往往卡在不同环节,排查得从 /proc/PID/status 看 Threads 和 NSpid,再比对各层限制值。










