最准确方法是统计/proc/[pid]/fd/下符号链接数:ls -1 /proc/1234/fd/ 2>/dev/null | wc -l;最大句柄数查cat /proc/1234/limits | grep "max open files";全局活跃句柄数用cat /proc/sys/fs/file-nr | awk '{print $2}'。

最准确、最直接的方法是统计进程 /proc/[pid]/fd/ 目录下的符号链接数量——每个链接对应一个当前打开的句柄,内核实时维护,不依赖权限或格式解析。
查单个进程当前实际占用的句柄数
运行以下命令(将 1234 替换为目标进程 PID):
ls -1 /proc/1234/fd/ 2>/dev/null | wc -l
说明:
-
ls -1逐行列出 fd 目录内容,每行一个句柄编号(如0、127、socket:[123456]) -
2>/dev/null必须加上,避免因权限不足(如查其他用户进程)导致错误信息混入计数 - 普通用户只能查自己启动的进程,例如查当前 shell 进程:
ls -1 /proc/$$/fd/ 2>/dev/null | wc -l
查该进程允许打开的最大句柄数
不要看当前终端的 ulimit -n,而要看进程启动时继承或设置的实际限制:
cat /proc/1234/limits | grep "Max open files"
输出类似:Max open files 1024 4096 files
含义:
- 左边
1024是 soft limit(运行中可调,但不能超 hard limit) - 右边
4096是 hard limit(仅 root 可提升) - systemd 服务默认不读
/etc/security/limits.conf,需在 service 文件中配LimitNOFILE=
为什么不用 lsof -p 统计句柄数
lsof -p 1234 | wc -l 看似方便,但存在多个可靠性缺陷:
- 默认跳过部分内核级 fd(如
eventpoll、inotify),高并发场景下漏数严重 - 输出含表头(第一行是列名),
wc -l会多算 1 行 - 遇到 DNS 解析失败或权限问题可能中断,尤其 fd 数过万时易超时或丢结果
- 对已删除但仍在引用的文件(
deleted状态),显示不稳定,造成计数波动
真正需要分析句柄类型(比如哪些是 socket、哪些是 regular file、是否有大量 CLOSE_WAIT)时,再用 lsof -p 1234 查看详情。
快速定位高句柄占用进程
若怀疑系统级句柄紧张,优先看全局活跃值,再找“大户”:
先看系统整体使用情况:cat /proc/sys/fs/file-nr | awk '{print $2}'
这个第二列数值才是当前**真实活跃占用**的句柄总数。
再找单个进程占用排名:
find /proc -maxdepth 1 -name '[0-9]*' -type d -exec bash -c 'if [ -d "$1/fd" ]; then echo "$1: $(ls -1 "$1/fd" 2>/dev/null | wc -l)"; fi' _ {} \; 2>/dev/null | sort -k2 -nr | head -10
该命令绕过权限报错,安全汇总 top 10 进程的 fd 实际用量。











