ulimit -u仅对当前shell生效,后台服务需通过pam limits.conf或systemd limitnproc配置,且须同步调整pid_max;三者最小值决定实际线程上限。

ulimit -u 设置只对当前 shell 生效,别指望它管住后台服务
临时执行 ulimit -u 65535 确实能让当前终端新开的进程/线程数上限变成 65535,但这个值只影响你手动敲命令启动的子进程。一旦关掉终端、SSH 断开重连,或者用 sudo -u appuser java -jar app.jar 这种方式启动服务,ulimit -u 就完全不生效——因为没走 PAM 登录流程,/etc/security/limits.conf 根本没加载。
/etc/security/limits.conf 配置后不生效?先查这三件事
写了 * soft nproc 65535 和 * hard nproc 65535 却没用,大概率卡在这几个环节:
- 没确认
/etc/pam.d/common-session(Debian/Ubuntu)或/etc/pam.d/system-auth(RHEL/CentOS)里是否真有session required pam_limits.so; - 只是
su - user切换用户,没真正登出再重新 SSH 登录——PAM session 不触发,配置就不加载; - 格式写错:必须
soft和hard分两行,不能合并成一行;*不匹配root,如果要限制 root,得单独加root soft nproc 65535。
systemd 服务压根不读 limits.conf,必须显式配 LimitNPROC
nginx、redis、Java 应用这些由 systemctl 管理的服务,完全无视 /etc/security/limits.conf。想改它们的进程/线程上限,只能在 service 文件里动手:
- 编辑
/etc/systemd/system/myservice.service,在[Service]段加一行:LimitNPROC=65535; - 全局设默认值(慎用):在
/etc/systemd/system.conf里加DefaultLimitNPROC=65535,然后执行sudo systemctl daemon-reload; - 验证是否生效:
systemctl show myservice | grep LimitNPROC,或查实际进程:prlimit -n $(pidof myservice) | grep "MAX processes"。
pid_max 设太小,ulimit 再大也没用
ulimit -u 和 /proc/sys/kernel/pid_max 必须同步调高,否则会卡在内核层。比如你设了 ulimit -u 65535,但 cat /proc/sys/kernel/pid_max 显示还是 32768,那第 32769 个 fork() 就直接报 fork: Cannot allocate memory 或 Java 的 unable to create new native thread。
- 临时改:
sudo sysctl -w kernel.pid_max=196608; - 永久改:写进
/etc/sysctl.d/99-pidmax.conf(比直接改/etc/sysctl.conf更安全),内容就一行:kernel.pid_max = 196608,然后运行sudo sysctl --system; - 注意:x86_64 架构上限约 4194304,设太高可能增加调度开销,一般 131072~196608 足够,别盲目堆高。
实际瓶颈永远是三个值里的最小值:ulimit -u、/proc/sys/kernel/pid_max、/proc/sys/kernel/threads-max。改完任何一个,都得重新验证,不能只看配置文件有没有改对。











