lsof如何揭示Linux一切皆文件的终极真相

lsof如何揭示Linux一切皆文件的终极真相

在 Linux 世界里,有一句几乎被奉为真理的话:

一切皆文件(Everything is a file)

但很多工程师只是在概念层面理解它。

直到你真正用好一个工具 —— lsof(List Open Files),你才会意识到:

它不是一句哲学,而是一个可以被“观测”的系统事实。

这篇文章,我们彻底讲清:

  • lsof 的底层原理
  • 它如何印证“一切皆文件”
  • 生产环境 15+ 高价值使用场景
  • 和 netstat / ss / ps 的区别
  • 排查线上问题的完整思维模型

一、什么是 lsof?

lsof 是一个 Unix/Linux 下用于列出进程打开文件的工具。

注意关键词:

不是“普通文件”
而是“所有文件描述符”

在 Linux 中,以下对象全部通过 file descriptor (FD) 表示:

对象 是否文件
普通文件
目录
TCP 连接
UDP 连接
Unix Socket
管道 pipe
匿名内存映射
设备文件 /dev/null
磁盘块设备

这就是 Linux 内核的统一抽象。


二、lsof 的底层原理

lsof 本质做了三件事:

  1. 遍历 /proc
  2. 读取 /proc/<pid>/fd/
  3. 解析符号链接指向

例如:

1
ls -l /proc/1234/fd

输出类似:

1
3 -> socket:[402653]4 -> /var/log/app.log5 -> anon_inode:[eventpoll]

这说明:

  • FD=3 是 socket
  • FD=4 是日志文件
  • FD=5 是 epoll

而 lsof 做的事情,就是帮你把这些结构:

结构化 + 关联进程 + 解析网络信息


三、最基础的使用

1️⃣ 查看所有打开文件

1
lsof

⚠️ 非常重,生产环境慎用。


2️⃣ 查看某个进程

1
lsof -p 1234

输出包含:

  • cwd(当前目录)
  • txt(执行文件)
  • mem(内存映射)
  • IPv4/IPv6
  • REG(普通文件)

你会发现:

一个 Java 进程,能打开几百甚至几千个文件。

这就是“一切皆文件”的具象体现。


四、最重要的生产级场景


场景 1:排查端口占用

1
lsof -iTCP:6443 -sTCP:LISTEN

输出:

1
java  1234  TCP *:8080 (LISTEN)

netstat 更精准,因为:

  • 可以直接看到 PID
  • 可以看到进程名
  • 可以过滤具体端口

场景 2:查找谁在监听端口

1
lsof -i -P -n | grep LISTEN
  • -P 不解析端口名
  • -n 不解析 DNS(避免卡住)

场景 3:查看进程打开文件数量(FD 泄漏)

1
lsof -p 1234 | wc -l

如果数字持续增长:

说明存在 FD 泄漏

常见原因:

  • 忘记关闭文件流
  • socket 未关闭
  • epoll FD 未释放

场景 4:排查 Too many open files

错误:

1
EMFILEToo many open files

排查步骤:

  1. 查看进程 FD 数量
1
ls /proc/1234/fd | wc -l
  1. 用 lsof 找出谁在吃FD
1
lsof -p 1234
  1. 查 ulimit
1
ulimit -n

场景 5:查看 TCP 连接

1
2
lsof -i tcp

指定:

1
2
lsof -i tcp:3306

你会看到:

1
2
java -> mysql

这直接揭示:

网络连接本质也是文件


场景 6:查看谁连接了某台远程机器

1
2
lsof -i @10.0.0.5


场景 7:查看 Unix Domain Socket

1
2
lsof -U

你会看到:

1
2
/var/run/docker.sock

这说明:

Docker API 其实是 Unix 文件。


场景 8:查看某个文件被谁使用

1
2
lsof /var/log/app.log


场景 9:查看内存映射文件

1
2
lsof | grep mem

Java 的 jar、so 库全部会显示。


场景 10:容器排查

1
2
nsenter -t <pid> -m -u -i -n -p lsof

你会发现:

  • 容器网络
  • 挂载文件
  • 共享 FD

都能观测到。


场景 11:排查 NFS 锁

1
2
lsof | grep nfs


场景 12:查看进程当前目录

1
2
lsof -p 1234 | grep cwd


场景 13:查看管道

1
2
lsof | grep pipe

Shell 管道本质:

1
匿名文件

五、lsof 如何证明“一切皆文件”

我们做个简单实验:

启动一个简单服务:

1
2
python3 -m http.server 8000

然后:

1
2
lsof -p <pid>

你会看到:

类型 说明
cwd 当前目录
txt Python 可执行
mem libc
IPv4 监听端口
pipe stdout
anon_inode epoll

这说明:

  • 网络是文件
  • 终端是文件
  • 内存映射是文件
  • 管道是文件

Linux 用 file abstraction 统一了:

存储 + 通信 + 设备 + 进程交互

这是一种极其优雅的内核设计。


六、lsof vs 其他工具

工具 能力
ps 进程信息
netstat 网络连接
ss socket 状态
lsof 文件 + 网络 + FD 全部

lsof 是统一视角。


七、架构师视角:为什么这很重要?

理解 lsof,你会获得三种能力:

1️⃣ 抽象能力

Linux 通过 file descriptor 统一所有资源。

这类似于:

  • JVM 一切皆对象
  • Kubernetes 一切皆 API
  • Unix 一切皆流

2️⃣ 故障排查模型

当线上出问题:

  • 端口占用
  • 磁盘满
  • FD 泄漏
  • 连接异常

你可以问自己:

是哪个文件没释放?


3️⃣ 性能优化视角

高并发服务器核心是:

  • socket 数量
  • epoll FD 数量
  • 文件句柄上限

这些都能用 lsof 观测。


八、终极理解

Linux 内核本质上维护:

1
2
3
4
task_struct   
└── files_struct
└── file descriptor table

所有资源都通过:

1
2
int fd

访问。

而 lsof:

就是 file descriptor table 的“可视化仪表盘”。


九、一个思维升级

当你下次看到:

1
Too many open files

不要只想到 ulimit。

而是要想到:

系统资源抽象失控了。

这才是真正的架构视角。

参考文档:https://man7.org/linux/man-pages/man8/lsof.8.html


十、总结

lsof 不只是一个命令。

它揭示的是 Linux 的核心哲学:

抽象统一,接口统一,资源统一。

当你真正掌握它:

  • 你会更快排查问题
  • 你会理解内核设计
  • 你会对系统资源有“可观测感”