lsof —— 谁占着这个文件或端口
lsof —— 谁占着这个文件或端口
分类:02 进程与网络诊断 适用:Linux / macOS(Linux 上读
/proc/*/fd,权限要求高) 一句话:lsof= list open files。Linux 里"一切皆文件",所以它也能查端口、socket、设备。
1. 它解决什么问题
- 端口被占用,起不来服务,是哪个进程?
- 文件删了但磁盘没释放(deleted 句柄)。
- 某个目录被哪个进程占着,导致
umount失败。 - 进程打开了多少文件,是否触及
ulimit -n。
2. 安装
apt install -y lsof
dnf install -y lsof
apk add lsof
3. 按端口 / 网络查
lsof -i :80 # 谁在用 80 端口
lsof -i :80 -sTCP:LISTEN # 只看监听
lsof -i tcp # 所有 TCP
lsof -i udp:53 # UDP 53
lsof -i @10.0.0.5 # 与某 IP 的所有连接
lsof -i @10.0.0.5:3306 # 指定 IP + 端口
lsof -i -n -P # -n 不解析主机名,-P 不解析端口名(快很多)
lsof -i 4 # 只 IPv4
lsof -i 6 # 只 IPv6
lsof -a -p 1234 -i # 某进程的网络连接(-a 表示条件 AND)
不加
-a时多个条件是 OR,这是lsof最常见的误用。
4. 按进程 / 用户 / 文件查
lsof -p 1234 # 该进程打开的所有文件
lsof -p 1234 -a -d 1,2 # 只看 fd 1、2
lsof -c nginx # 按命令名(前缀匹配,<=9 字符)
lsof -c nginx -c php # 多个 OR
lsof -u nginx # 按用户
lsof -u ^root # 排除 root
lsof /var/log/nginx/access.log # 谁打开了这个文件
lsof +D /data # 递归查目录下所有被打开的文件(慢)
lsof +L1 # 链接数为 0 的文件(已删除但被占用)
lsof /dev/sdb # 谁占着设备(umount 失败时用)
lsof -t /path # 只输出 PID,便于管道
5. 输出怎么读
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1234 root cwd DIR 253,0 4096 2 /
nginx 1234 root txt REG 253,0 1256448 131074 /usr/sbin/nginx
nginx 1234 root 1w REG 253,0 104857600 524301 /var/log/nginx/access.log
nginx 1234 root 6u IPv4 1234567 0t0 TCP *:80 (LISTEN)
| 列 | 含义 |
|---|---|
FD |
文件描述符。cwd 当前目录、txt 程序本体、mem 内存映射、数字为 fd |
| FD 后缀 | r 读、w 写、u 读写 |
TYPE |
REG 普通文件、DIR 目录、IPv4/IPv6 网络、CHR 字符设备、FIFO、unix |
DEVICE |
设备号(主,次) |
SIZE/OFF |
文件大小或偏移 |
NODE |
inode 号 |
NAME |
路径或连接四元组 |
6. 实战场景
6.1 端口占用
lsof -i :8080 -sTCP:LISTEN
# 或
ss -lntp | grep :8080
fuser -n tcp 8080 # 更轻量
处理:确认进程归属,systemctl stop 或 kill,别直接杀不认识的进程。
6.2 文件已删但磁盘没释放
lsof +L1
# 或
lsof | grep -i deleted
java 1234 app 3w REG 253,0 8589934592 524301 /data/app.log (deleted)
处理方式(不要重启服务):
# 方式一:清空该 fd(推荐,进程继续写,空间释放)
: > /proc/1234/fd/3
# 方式二:重启/重载该进程
systemctl reload <service>
df 显示满但 du 算不出来,99% 是这个原因。
6.3 umount 失败:设备忙
lsof +f -- /mountpoint # 或
lsof /mountpoint
fuser -vm /mountpoint
常见占用者:shell 的 cwd、tail -f 的日志、nfs 客户端。
6.4 检查文件句柄是否耗尽
lsof -p <PID> | wc -l
cat /proc/<PID>/limits | grep 'open files'
ls /proc/<PID>/fd | wc -l
报 Too many open files 时,先确认是泄漏还是限额太小。泄漏特征:fd 数持续单调上涨。
按类型统计泄漏源:
lsof -p <PID> | awk '{print $5}' | sort | uniq -c | sort -nr
6.5 找出日志被谁在写
lsof /var/log/app/*.log
# 迁移日志目录前必须确认没有进程持有旧 inode
7. 常见坑
- 性能极差:
lsof全量扫描会遍历所有进程的 fd,机器上进程多时可能跑几十秒甚至卡顿。加-n -P,并尽量带条件。 - 必须 root 才看得全:普通用户只能看到自己进程的 fd,会得出"没人占用"的错误结论。
- 多条件是 OR:
lsof -p 1234 -i是"该进程 OR 有网络连接",要 AND 必须加-a。 -c只匹配前 9 个字符:长命令名要用-c配合grep或直接用pgrep -f。- deleted 文件要看 fd 号:不同线程/fd 指向同一 inode,清一个不一定够。
- 容器内看不到宿主机:命名空间隔离,需在宿主机查,或用
nsenter。 - NFS 上
lsof可能挂住:网络存储异常时lsof会一起卡,先用-b避免阻塞调用。 lsof -i输出会解析域名:慢,加-n。+D递归很慢:大目录用find+lsof组合更可控。
8. 速查表
lsof -i :<port> # 端口占用
lsof -i :<port> -sTCP:LISTEN # 仅监听
lsof -i @<ip>:<port> # 指定连接
lsof -p <PID> # 进程打开的文件
lsof -u <user> # 按用户
lsof /path/to/file # 谁打开了文件
lsof +D /dir # 目录下被打开的文件
lsof +L1 # 已删除仍占用
lsof -t /path # 只要 PID
lsof -a -p <PID> -i # AND 组合
lsof -nP -i # 不解析,速度快
# 释放已删文件
: > /proc/<PID>/fd/<N>
# 替代
ss -lntp # 端口
fuser -vm /mount # 设备占用