linux无内置命令生成文件描述符分布图表,需用ls -l /proc/[pid]/fd或lsof -p [pid]提取数据后交由gnuplot/matplotlib绘图;推荐lsof -p [pid] -f t统计type类型更准确,或用ascii柱状图快速查看分布。

Linux 没有内置命令直接生成「文件描述符分配情况分布图表」(比如柱状图、热力图),ls -l /proc/[PID]/fd 或 lsof -p [PID] 只能输出列表,不带可视化。真要画图,得自己提取数据再喂给绘图工具。
怎么从 /proc/[PID]/fd 提取 fd 类型分布
/proc/[PID]/fd 下每个数字项是符号链接,目标路径隐含类型线索。直接 ls -l 输出里看箭头右边的字符串即可粗略分类:
-
/dev/.*→ 设备文件(如/dev/null、/dev/pts/0) -
socket:[.*]→ 套接字(TCP/UDP/unix domain socket) -
anon_inode:[.*]→ 内核匿名对象(如eventpoll、inotify、timerfd) -
/proc/[0-9]+/fdinfo/.*→ 不会出现,那是另一层路径 -
/path/to/file→ 普通文件或目录(注意软链接可能指向其他位置)
实操建议:
- 用
readlink -f /proc/[PID]/fd/<em> 2>/dev/null | grep -E '^(socket|anon_inode|/dev|/)' | sed 's|^(/dev/[^ ]</em>)|device|; s|^socket:[.<em>]|socket|; s|^anon_inode:[.</em>]|anon_inode|; s|^/.*$|regular|' | sort | uniq -c | sort -nr - 这段命令能统计出各类型 fd 的数量,结果可存为 CSV 后导入 gnuplot / matplotlib
常见坑:
-
readlink -f对socket:[12345]会失败,需先过滤掉再处理 -
anon_inode:[eventpoll]和anon_inode:[timerfd]要靠正则区分,否则全归一类会掩盖 epoll 使用量 - 某些容器环境(如 Docker)中
/proc/[PID]/fd链接目标可能被挂载隔离,readlink返回空或权限拒绝
用 lsof -p [PID] 解析 fd 类型更可靠
lsof 自带 TYPE 字段(REG、DIR、IPv4、IPv6、unix、CHR、FIFO 等),比解析符号链接更准:
- 运行
lsof -p [PID] -F t 2>/dev/null | grep '^t' | sort | uniq -c | sort -nr可提取 TYPE 统计(-F t输出机器可读格式,每行以t开头) - 若需同时看 FD 编号和 TYPE:
lsof -p [PID] -F ftn 2>/dev/null | paste - - - | awk '{print $2, $4}' | sort | uniq -c
注意点:
-
lsof在非 root 用户下可能看不到其他用户进程的 fd(尤其涉及 socket 或 /proc 映射) - 某些内核模块(如 eBPF 程序持有的 fd)在
lsof中显示为UNKNOWN,但/proc/[PID]/fd里能看到anon_inode:[bpf] -
lsof -p [PID]默认包含标题行,脚本处理时记得tail -n +2或用-F格式规避
快速生成简易分布文本图(不用外部工具)
如果只是想一眼看出哪类 fd 占多数,不用画图,可用 shell 拼个 ASCII 柱状图:
lsof -p [PID] 2>/dev/null | awk 'NR>1 {type[$5]++} END {for (t in type) print t, type[t]}' | sort -k2 -nr | head -10 | awk '{printf "%-12s %s %s\n", $1, sprintf("%*s", $2, ""), $2}'
输出类似:
IPv4 ██████████████████████████ 217 REG ████████████████ 132 unix ███████ 58 DIR ███ 24
关键限制:
- 这种方式依赖
lsof的$5字段(TYPE 列),不同版本列序可能微调,建议先跑lsof -p [PID] | head -2确认 - 宽度计算用空格填充,终端宽度不够时会折行,不适合管道进 less,更适合一次性查看
真正做容量分析或长期监控时,别硬套图表。重点其实是:
-
cat /proc/[PID]/status | grep -E 'FDSize|FDs'看是否接近上限 -
ls /proc/[PID]/fd | wc -w和ulimit -n对比,确认是否真卡在 limit - 大量
anon_inode:[eventpoll]通常意味着用了 epoll;大量socket:[...]但没对应业务连接,可能是泄漏
图形只是表象,fd 分布背后是程序 I/O 模型和资源管理逻辑——这点最容易被忽略。











