lsof 是什么
lsof 即 list open files,用来列出进程当前打开的文件描述符:普通文件、目录、块设备、字符设备、管道、socket 都在范围之内。Linux 里一切皆文件,所以它同时也是查端口占用、查句柄泄漏、查「删了文件磁盘却没释放」的工具。它通过遍历 /proc 下各进程的信息拼出结果,看到的只是某一时刻的快照。
基本信息
| 适用平台 | Linux、Unix;多数发行版需要单独安装(Debian 系与 RHEL 系包名都是 lsof) |
|---|---|
| 命令语法 | lsof [选项] [路径 | +d 目录 | +D 目录 | -i :端口] |
| 常用选项 | -p PID / -u 用户 / -c 命令前缀 / -i 网络连接 / -t 只输出 PID / +L1 链接数小于 1 / -n 不解析主机名 / -P 不解析端口名 |
| 权限要求 | 查看他人进程需要 root;普通用户只能看到自己名下的 |
典型使用场景
- 删了日志磁盘仍然满:lsof +L1 /var/log 找出还在持有已删除文件的进程
- 端口占用定位:lsof -i :8080 看谁在监听或连接这个端口
- 句柄泄漏排查:lsof -p PID | wc -l 定时统计,观察数量是否持续增长
- 卸载存储或文件系统之前:lsof /dev/sdb1 与 lsof +D /data 找出占用者
- 安全排查:lsof -nP -i 列出全部网络连接及对应进程
经典用法
经典用法
lsof +L1 /var/log # 找出已删除但仍被持有的文件(空间不释放的元凶)
lsof +D /data # 递归列出目录下被打开的文件(较慢)
lsof -p 1234 # 某进程打开的一切
lsof -i :8080 # 谁占用了 8080 端口
lsof /dev/sdb1 # 谁在用这个块设备
lsof -t /var/log/app.log # 只输出 PID,方便直接交给 kill
lsof -nP -i # 全部网络连接,不解析主机名与端口名释放被删除文件占用的空间
释放被删除文件占用的空间
lsof +L1 /data # 记下 PID 与 NAME 两列
systemctl restart app # 重启持有者,句柄关闭后空间立即释放
lsof +L1 /data # 复查一次,确认已经干净
# 不能重启的进程:可尝试向 /proc/PID/fd/N 写入空内容截断文件
# 但这会打乱应用对文件偏移的假设,只作为最后手段输出逐列读法
| 列 | 含义 | 怎么看 |
|---|---|---|
| COMMAND | 进程名,过长会被截断 | 与 ps 的该列对应,同名多实例要靠 PID 区分 |
| PID | 进程号 | 加 -t 可只输出这一列 |
| USER | 进程属主 | 用来分辨谁在跑这个进程 |
| FD | 文件描述符:cwd、txt、mem 或数字 | 数字就是进程打开的 fd 编号 |
| TYPE | 文件类型:REG 普通文件、DIR 目录、CHR 字符设备、IPv4 网络套接字 | 出现 IPv4 或 IPv6 说明是网络连接 |
| DEVICE | 设备号 | 与 df 对照能判断落在哪块盘 |
| SIZE/OFF | 文件大小或当前偏移 | 已删除文件这里常显示很大的值 |
| NODE | inode 号 | 已删除文件的这一列常见为 0 |
| NAME | 文件路径或 socket 地址,删除后带 (deleted) | 定位问题的关键就在这一列 |
加 -L1 的含义是「链接数小于 1」,也就是文件已经没有任何目录项指向它,只剩进程手心里的句柄。这正是「df 显示空间被占、du 却找不到对应文件」的经典现象。
不带参数运行 lsof 会遍历全系统所有进程的文件描述符,大机器上又慢又重,还可能需要 root 才看得全。生产环境尽量带上过滤条件,例如 -p、-u、-c、具体路径或端口。
权限不足或机器上没有 lsof 时,可以用替代手段:fuser -v 路径 看占用者,逐个查看 /proc/PID/fd 目录,网络部分用 ss -tnp。
排查句柄泄漏不能只看一次快照:每隔一段时间统计 lsof -p PID | wc -l,数值随时间单调上升才说明真在泄漏,围绕某个水平波动属于正常现象。
查看网络连接时加上 -n 与 -P,跳过主机名与端口名的解析,结果出得更快,也避免 DNS 反查卡住命令。