必须同步调整用户软硬限、系统总池、systemd服务限、pam加载机制四层限制;先执行ulimit -sn/-hn、cat /proc/sys/fs/file-max、systemctl show服务|grep limitnofile定位瓶颈,再针对性修复。

不能只改 ulimit -n,必须同步调四层限制:用户软硬限、系统总池、systemd 服务限、PAM 加载机制——漏一层,服务照样报错。
查清当前哪一层卡住了
先别急着改配置,先定位瓶颈在哪。执行这三步:
-
ulimit -Sn和ulimit -Hn:看当前会话软硬限制是否一致且足够(比如都是 65535) -
cat /proc/sys/fs/file-max:系统级总池是否 ≥ 单进程上限 × 预期并发进程数(建议 ≥ 1048576) -
systemctl show nginx | grep LimitNOFILE(把nginx换成你的服务名):确认 systemd 是否已加载自己的句柄限制
常见现象是 ulimit -Sn 显示 65535,但服务日志仍报错——说明它根本没继承这个值,大概率是 systemd 绕过了 PAM,或 PAM 根本没加载。
/etc/security/limits.conf 配了却无效的典型原因
这个文件不是“写完就生效”,它依赖 PAM 模块在登录时注入,出问题基本集中在三点:
- 没启用
pam_limits.so:检查/etc/pam.d/common-session(Ubuntu/Debian)或/etc/pam.d/system-auth(RHEL/CentOS),必须有未注释的session required pam_limits.so - 用户名匹配顺序错:如果同时写了
* soft nofile 1024和www-data soft nofile 65535,而*在前,那www-data就永远拿不到 65535 - 没真正重新登录:改完必须 SSH 断开重连,或图形界面登出再进;
source ~/.bashrc或新开终端窗口完全无效
验证方式:用目标用户身份登录后,立刻执行 ulimit -n,再 ps -o pid,uid,comm -u $(whoami) 确认进程 UID 匹配。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
systemd 服务必须单独配 LimitNOFILE
/etc/security/limits.conf 对 systemctl start 启动的服务完全不起作用,因为 systemd 不走 PAM 登录流程。必须显式配置:
- 单个服务:编辑
/etc/systemd/system/nginx.service,在[Service]段下加LimitNOFILE=65535 - 全局生效:改
/etc/systemd/system.conf,在[Manager]下加DefaultLimitNOFILE=65535 - 改完必须执行
sudo systemctl daemon-reload,再sudo systemctl restart nginx
验证是否生效:cat /proc/$(pgrep nginx)/limits | grep "Max open files",看 Soft Limit 和 Hard Limit 是否都已更新。
fs.file-max 太小会导致所有进程一起跪
即使每个进程都设了 65535,如果 /proc/sys/fs/file-max 只有默认的 32768,系统总池耗尽后,新进程连启动都失败,fork: Cannot allocate memory 或直接报 Too many open files。
- 临时调高:
sudo sysctl -w fs.file-max=1048576 - 永久生效:往
/etc/sysctl.conf追加fs.file-max = 1048576,再运行sudo sysctl -p - 注意:这个值不是越大越好,它占用内核内存,一般设为预期最大并发句柄总数的 1.2 倍即可
最容易被忽略的是这一层——很多人调完 ulimit 和 systemd 就以为万事大吉,结果压测一上量,整个系统开始随机崩,查半天才发现是 file-max 先撑不住了。










