摘要 :
lsof(List Open Files)是 Linux 系统排查问题的利器。本文从核心原理(/proc文件系统)出发,系统讲解端口占用排查、已删除文件空间找回、进程文件查看等高频场景,并涵盖组合查询、输出格式化等高级技巧与实战案例,帮你快速定位线上故障。
线上服务器突然报磁盘空间不足,df 一看还有 30%,但 du 统计出来却只有 10%。这种情况你遇到过吗?大概率是某个进程打开了已删除的文件,文件句柄没释放。
这时候 lsof 就派上用场了。
lsof 是什么
lsof 全称 List Open Files ,用于列出当前系统所有打开的文件。在 Linux 里,一切皆文件------普通文件、目录、网络套接字、管道、设备......这些都是文件。所以 lsof 能看到的不只是文件,还有网络连接、进程通信等。
核心原理:从 /proc 文件系统读取
lsof 的数据来源是 /proc 文件系统。每个进程在 /proc/<pid>/fd/ 目录下都有文件描述符的符号链接:
bash
# 查看进程 1234 打开的文件描述符
ls -la /proc/1234/fd/
lrwx------ 1 root root 64 May 19 10:00 0 -> /dev/null
lrwx------ 1 root root 64 May 19 10:00 1 -> /dev/pts/0
lrwx------ 1 root root 64 May 19 10:00 2 -> /dev/pts/0
lrwx------ 1 root root 64 May 19 10:00 3 -> /var/log/app.log
lrwx------ 1 root root 64 May 19 10:00 4 -> socket:[12345]
lsof 本质上是遍历这些信息并格式化输出。理解这一点,遇到权限问题或特殊情况时就知道该怎么排查了。
常用场景与命令
1. 查看端口占用
bash
# 查看谁在监听 8080 端口
lsof -i :8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1234 root 6u IPv4 12345 0t0 TCP *:8080 (LISTEN)
# 只显示 TCP 连接
lsof -i TCP:8080
# 查看所有网络连接
lsof -i
输出字段解释:
- FD : 文件描述符,
u表示读写模式 - TYPE: 文件类型,IPv4/IPv6 表示网络套接字
- NODE: 内核中的 inode 编号
- NAME: 文件名或连接信息
2. 查看进程打开的文件
bash
# 查看指定进程打开的所有文件
lsof -p 1234
# 查看多个进程
lsof -p 1234,5678,9012
# 只看普通文件(排除套接字、管道等)
lsof -p 1234 | grep REG
3. 找回已删除但仍占空间的文件
这是 lsof 最经典的用法。文件被删除后,如果有进程仍持有其句柄,磁盘空间不会释放:
bash
# 找出已删除但仍被打开的文件
lsof | grep deleted
java 1234 root 1w REG 8,1 1073741824 12345 /var/log/app.log (deleted)
# 恢复文件内容(通过 /proc)
cp /proc/1234/fd/1 /tmp/recovered.log
# 彻底释放空间:杀死进程或重启服务
kill -HUP 1234
4. 查看用户打开的文件
bash
# 查看指定用户打开的文件
lsof -u nginx
# 排除某个用户
lsof -u ^root
# 查看多个用户
lsof -u nginx,mysql
5. 查看目录被谁占用
bash
# 查看谁在使用 /var/log 目录
lsof +D /var/log
# 递归查看(+D 会递归,+d 不会)
lsof +d /var/log
6. 查看文件被谁打开
bash
# 查看指定文件被哪个进程打开
lsof /var/log/app.log
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
tail 5678 root 3r REG 8,1 1024 12345 /var/log/app.log
高级技巧
组合条件查询
bash
# 查看 nginx 进程的网络连接
lsof -c nginx -i
# 查看指定用户的 TCP 连接
lsof -u nginx -i TCP
# 查看指定进程的网络连接
lsof -p 1234 -i
# 使用 AND 逻辑(同时满足)
lsof -a -c nginx -i TCP
# 使用 OR 逻辑(默认)
lsof -c nginx -c mysql
输出格式化
bash
# 只输出 PID
lsof -t -i :8080
# 配合 kill 使用
kill -9 $(lsof -t -i :8080)
# 输出为 CSV 格式(便于脚本处理)
lsof -F pcn | awk '/^p/{pid=substr($0,2)} /^c/{cmd=substr($0,2)} /^n/{print pid","cmd","substr($0,2)}'
查看块设备
bash
# 查看谁在使用 /dev/sda1
lsof /dev/sda1
# 查看所有块设备
lsof +c 0 | grep -E "^COMMAND|/dev/sd"
性能考量
lsof 需要遍历所有进程的 /proc/<pid>/fd/ 目录,在进程数很多的系统上会比较慢。几个优化建议:
- 缩小查询范围:指定进程、用户或端口,避免全量扫描
- 使用 -n 参数:不解析主机名,加快输出速度
- 使用 -P 参数:不解析端口名,直接显示数字
bash
# 快速查询,不解析名称
lsof -n -P -i :8080
与其他工具对比
| 工具 | 主要用途 | 优势 |
|---|---|---|
| lsof | 列出打开的文件 | 全面,支持网络、文件、设备 |
| fuser | 查看谁在使用文件/套接字 | 轻量,适合脚本 |
| ss | 查看套接字统计 | 快速,取代 netstat |
| netstat | 查看网络连接 | 传统工具,逐渐被 ss 取代 |
bash
# fuser 查看 8080 端口占用
fuser 8080/tcp
# ss 查看 8080 端口
ss -tlnp | grep 8080
实战案例
案例 1:排查 "Too many open files"
bash
# 查看系统打开文件限制
ulimit -n
# 查看指定进程打开的文件数量
lsof -p 1234 | wc -l
# 查看所有进程打开文件数排序
lsof | awk '{print $1}' | sort | uniq -c | sort -nr | head
案例 2:排查磁盘空间消失
bash
# 现象:df 显示空间不足,但 du 统计正常
df -h
du -sh /*
# 用 lsof 找出罪魁祸首
lsof | grep deleted | sort -k7 -nr | head
# 解决:重启对应服务或杀死进程
案例 3:排查服务启动失败(端口被占用)
bash
# 启动服务报 "Address already in use"
lsof -i :8080
# 强制杀掉占用端口的进程
kill -9 $(lsof -t -i :8080)
总结
lsof 是排查线上问题的利器,熟练掌握能帮你快速定位:
- 端口占用问题
- 磁盘空间消失问题
- 文件锁定问题
- 网络连接追踪
记住几个核心参数:-i 查网络、-p 查进程、-u 查用户、+D 查目录。遇到问题时,先想到 /proc 文件系统,再配合 lsof 工具,基本都能找到答案。
相关工具:
- Linux 命令速查 - 150+ Linux 命令详解
- 端口检测器 - 在线检测端口是否开放
