查系统级最大句柄数应直接读/proc/sys/fs/file-max,该值为内核允许的全局文件描述符总数;查当前已用总数须看/proc/sys/fs/file-nr第二列,它表示活跃占用数,是监控告警的核心指标。

查系统级最大句柄数:直接读 /proc/sys/fs/file-max
这是最权威、无权限依赖的方式,返回的就是内核允许的全局最大值。运行:cat /proc/sys/fs/file-max
输出是一个纯数字,比如 2097152,它代表整个系统所有进程加起来最多能打开多少个文件描述符。
注意:file-max 不是“当前已用”,也不是“某个进程上限”,它只管总量。如果这个值太小(比如默认的 8192 或 65536),高并发服务(如 Node.js 网关、Redis 集群)很容易撞墙,哪怕单个进程限制调得再高也没用。
查当前已用句柄总数:盯紧 /proc/sys/fs/file-nr 的第二列
/proc/sys/fs/file-nr 输出三列,例如:12480 3210 2097152
真正该关注的是**第二列(3210)**——它表示当前被实际占用的句柄数,即“活跃使用中”的数量。
- 第一列(12480)= 已分配句柄总数(含未使用)
- 第二列(3210)= 当前真正被进程持有的句柄数 → 这是你监控告警的核心指标
- 第三列(2097152)=
file-max值,和上面一致
别用 lsof | wc -l 替代它:权限失败会中断统计,还混入表头和空行;lsof -i 更糟,只扫网络 socket,漏掉 eventfd、timerfd、普通文件等大量非网络句柄。
查单个进程的句柄上限和实际用量
进程的真实限制不在 ulimit -n,而在它的 /proc/[pid]/limits:
cat /proc/1234/limits | grep "Max open files"
输出类似:Max open files 1024 4096 files,左边是 soft limit(运行时可调),右边是 hard limit(root 才能提)。
实际用了多少?最准方法是:ls -1 /proc/1234/fd/ 2>/dev/null | wc -l
比 lsof -p 1234 | wc -l 更快、更稳定,尤其在 fd 数过万时不会卡住或丢数。
注意:普通用户只能读自己进程的 /proc/[pid]/fd/;查别人进程需 root 权限,否则 2>/dev/null 是必须的,否则计数被错误干扰。
为什么改了 limits.conf 还是报 Too many open files
因为 systemd 服务压根不认 /etc/security/limits.conf。nginx、redis、java 应用这些通过 systemctl start 启动的服务,其 LimitNOFILE 必须显式写在 service 文件里:
- 临时测试:用
systemctl edit nginx加一行LimitNOFILE=65536 - 生效要重载:
systemctl daemon-reload && systemctl restart nginx - 验证是否生效:
cat /proc/$(pgrep nginx -n)/limits | grep files
别指望改完 limits.conf 就一劳永逸——它只对 PAM 登录会话(ssh、console)有效,对 cron、nohup、docker 容器内进程也无效。真正容易被忽略的是:即使你把所有参数都设高了,只要 /proc/sys/fs/file-nr 第二列持续逼近第三列的 80%,就得查泄漏,而不是继续调参。











