系统级已用fd总数为/proc/sys/fs/file-nr第一列数值,如12480;总上限以/proc/sys/fs/file-max为准;禁用lsof | wc -l统计;进程限制(ulimit、nr_open)与系统限制独立。

查系统级已用 fd 总数:盯紧 /proc/sys/fs/file-nr 第一列
执行 cat /proc/sys/fs/file-nr,输出类似 12480 0 2097152 的三列数字。第一列(12480)就是当前内核已分配出去的文件描述符总数——它包含所有进程打开的 fd,也含已关闭但尚未回收的残留项。这个值才是系统真实负载,不是估算值。第二列现代内核基本恒为 0,可忽略;第三列等于 /proc/sys/fs/file-max,是硬上限。
查系统总上限:/proc/sys/fs/file-max 才是最终答案
cat /proc/sys/fs/file-max 返回的是内核当前实际生效的系统级 fd 总数上限。它比 sysctl fs.file-max 更可信,因为后者在 RHEL 8+ 等系统中可能只是 systemd-sysctl 加载的缓存值,而 /proc 下的是运行时真实值。如果你刚改过 sysctl.conf 却没生效,先确认这里是否已更新。
别用 lsof | wc -l 统计总数——结果严重失真
这个命令会把每个线程、每个 socket 连接、每个管道都当独立条目计数,还会重复统计共享 fd 的多线程进程,甚至包含权限不足导致的报错行。实测偏差常达 2–5 倍。真正需要总量时,只认 /proc/sys/fs/file-nr 第一列;想看分布,再用 lsof 按进程或类型过滤。
进程限制和系统限制是两回事,不能混着看
即使 /proc/sys/fs/file-max 是 200 万,某个进程仍可能卡在 1024 —— 因为它的 /proc/[pid]/limits 软限制没调。同样,ulimit -n 只影响当前 shell 启动的进程,对 systemd 服务完全无效。最易被忽略的是 fs.nr_open:它是单进程硬上限,默认 1048576,若你把 file-max 设得更高却不调它,新进程的 open() 仍会失败。











