lsof:找出占用端口的进程与被删除的文件
发布时间:2026-06-19 17:58       
更新时间:2026-06-19 23:57
报错 Address already in use 是服务器上的常客,第一步永远是搞清谁占着端口。lsof(list open files)就是干这个的,Linux 下"一切皆文件",网络连接、普通文件、目录都能用它查。下面按三个常见场景走。
## 场景一:查端口占用
需要 root 权限,否则只能看到自己的进程:
```
sudo lsof -i :80
sudo lsof -i tcp:443
```
输出里 COMMAND、PID、USER 三列就是答案,确认无用后 kill 对应 PID 释放端口。两个常用变体:加 -P 让端口保持数字不做服务名转换;sudo lsof -i -P | grep LISTEN 列出全部监听端口。按用户过滤也行,lsof -u www 看 www 用户打开的所有文件。还有个细节:IPv6 与 IPv4 是两行输出,只处理了 IPv4 那行还不够,两行都要确认。
## 场景二:查谁在动某个目录
卸载目录时提示 target is busy,用 +D 递归找出占用者:
```
sudo lsof +D /data
```
目录大时这条命令会慢,因为它要遍历整棵树。只想确认单个文件,直接 sudo lsof /var/log/messages。输出里 FD 列值得认识一下:cwd 是工作目录,rtd 是根目录,数字加 w/r/u 分别是写、读、读写打开的文件。
## 场景三:文件删了,空间没释放
这是 lsof 最经典的应用。日志文件被 rm 后,若进程还握着文件句柄,磁盘空间不会立刻归还,df 显示满、du 却对不上总数,两者可能差出几十 G。线上就出过日志删了两个月、空间始终不还的案例,最后靠这条命令两分钟定位。确认方法:
```
sudo lsof | grep deleted
```
SIZE/OFF 列很大、NAME 列带 (deleted) 标记的就是元凶。处理顺序:先看能否重启或 reload 对应服务;急的办法是清空句柄,echo > /proc/PID/fd/N(N 从上一条输出里查);还有一招,cat /proc/PID/fd/N > recover.log 能把"已删除"的内容救回来,前提是进程还活着,服务一重启句柄就真没了。稳的办法是养成用 > 截断日志、或交给 logrotate 的习惯,别对正在写的日志直接 rm。
## 验证
每步操作后复查:端口场景再跑一次 lsof -i :80 应无输出;空间场景 df -h 与 du -sh 的差值应缩小到正常范围。lsof 输出量大,不确定时先 grep 再动手,比直接 kill 稳妥。