查进程真实限制应读/proc/[pid]/limits而非ulimit -n,因后者仅反映当前shell设置,对systemd等后台服务无效;/proc/sys/fs/file-nr第二列才是系统当前真实占用句柄数,/proc/[pid]/fd/计数比lsof更准更快。

查进程真实限制:直接读 /proc/[pid]/limits
别信 ulimit -n,它只反映当前 shell 的设置,对已运行的后台服务(比如 systemd 启动的 nginx、Java 进程)完全无效。真正生效的限制藏在 /proc/[pid]/limits 里。
执行:cat /proc/1234/limits | grep "Max open files"
输出形如:Max open files 1024 4096 files
左边是 soft limit(运行时可调),右边是 hard limit(root 才能提)。注意:这个值是进程启动时继承或被 setrlimit 设置的,不是当前已用数。
看系统总上限和实时占用:/proc/sys/fs/file-nr 第二列才是关键
/proc/sys/fs/file-nr 输出三列,例如 12480 3210 2097152:
• 第一列 = 已分配句柄总数(含未使用)
• 第二列 = 当前真正被进程持有的句柄数 → 这是你监控告警该盯的数字
• 第三列 = /proc/sys/fs/file-max,即内核允许的全局最大值
别用 lsof | wc -l 替代它:权限失败会中断统计,还混入表头;lsof -i 更糟,只扫网络 socket,漏掉 eventfd、timerfd、普通文件等大量非网络句柄。
查某个进程开了多少句柄:ls /proc/[pid]/fd/ 比 lsof -p 更准更快
Linux 中每个打开的句柄在 /proc/[pid]/fd/ 下对应一个符号链接,数目录项就是真实数量。
执行:ls -1 /proc/1234/fd/ 2>/dev/null | wc -l
比 lsof -p 1234 | wc -l 快得多,尤其 fd 数过万时不会卡住或丢数。
注意:
• 普通用户只能读自己进程的 /proc/[pid]/fd/
• 查别人进程必须 root,否则 2>/dev/null 不可少,否则权限错误会干扰计数
为什么改了 /etc/security/limits.conf 却没生效
因为该文件只对 PAM 登录会话生效(ssh 登录、console login),对以下场景完全无效:
• systemd 管理的服务(nginx、redis、java app)→ 必须在 service 文件里加 LimitNOFILE=65536
• cron 任务、nohup 启动的进程、容器内进程
• root 用户默认不受 * 配置影响,需单独写 root soft nofile 65536
改完要重载:systemctl daemon-reload && systemctl restart your-service,然后去 /proc/[pid]/limits 验证,别只看 ulimit -n 的 shell 值。











