查系统当前已用句柄总数应只看 /proc/sys/fs/file-nr 第二列,它表示内核统计的活跃占用数,如 12480 3210 2097152 中的 3210,是监控告警唯一可靠指标;lsof | wc -l 因权限、表头、空行及漏统计非网络句柄而失准。

查系统当前已用句柄总数,只看 /proc/sys/fs/file-nr 第二列
别用 lsof | wc -l,它会因权限失败中断、混入表头和空行,还漏掉 eventfd、timerfd、已删除但仍在引用的文件(DEL 状态)等非网络句柄。/proc/sys/fs/file-nr 是内核原生统计,三列数字如 12480 3210 2097152,其中第二列 3210 就是当前真正被进程持有的活跃句柄数——这是监控告警唯一该盯的指标。
查单个进程实际用了多少句柄,用 ls -1 /proc/[pid]/fd/
lsof -p [pid] 在 fd 数过万时容易卡住或丢数;而 ls -1 /proc/[pid]/fd/ 2>/dev/null | wc -l 直接读目录项,更快更稳。注意:
• 普通用户只能读自己进程的 /proc/[pid]/fd/,查别人必须 root 权限
• 2>/dev/null 不可省,否则权限拒绝会输出错误信息,干扰 wc -l 计数
• $$ 可代指当前 shell 的 PID,比如查自己: ls -1 /proc/$$/fd/ 2>/dev/null | wc -l
查单个进程的句柄上限,别信 ulimit -n
ulimit -n 只反映当前 shell 启动的子进程默认软限制,对 systemd 管理的服务、docker 容器里跑的进程完全不生效。真正生效的限制在 /proc/[pid]/limits 里:
• 运行 cat /proc/[pid]/limits | grep "Max open files"
• 输出类似 Max open files 1024 4096 files,左边是 soft limit(运行时可调),右边是 hard limit(root 才能提)
• systemd 服务需单独配 LimitNOFILE=,不是改 /etc/security/limits.conf 就能覆盖
为什么 lsof -i 统计不准
lsof -i 只扫网络 socket,完全不包括普通文件、管道、设备节点、inotify 实例、epoll fd 等——高并发服务(如 Node.js 网关、Redis)大量使用这些非 socket 句柄,只跑 lsof -i 会严重低估真实压力。真要定位大户,用:
• lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head -10(第一列是句柄数,第二列是 PID)
• 再配合 ps -p [pid] -o pid,comm,args 看具体命令
• 注意:容器内看到的 /proc/sys/fs/file-nr 是宿主机视角,不是隔离后值
最易被忽略的是:系统级 file-max 和进程级 RLIMIT_NOFILE 是两层独立限制,调高单个进程上限没用,如果 /proc/sys/fs/file-max 太小(比如默认 65536),整个系统照样会 Too many open files。


















