在CentOS系统运维过程中,文件被占用是一个高频故障点。典型表现包括:rm删除了大日志文件后磁盘空间没有释放、程序报错提示文件被另一个进程使用、端口启动时报Address already in use等。这些问题的根源都在于Linux允许一个文件同时被多个进程持有,而排查的关键工具就是lsof。本文结合CentOS环境,详细介绍lsof的安装、核心参数以及各类占用场景的排查思路。

lsof是什么以及CentOS下如何安装
lsof全称是list open files,即列出当前系统打开的文件。Linux继承了一切皆文件的设计理念,普通文件、目录、字符设备、网络套接字、管道、共享库都属于文件的范畴。因此lsof能展示的信息远比名字所暗示的丰富:每个进程打开了哪些文件、哪个进程占用了某个端口、哪个用户正在读写某个目录,都可以通过它查到。
在较完整的CentOS发行版中lsof一般预装了,如果没有,可以用yum直接安装:
yum install -y lsof # CentOS 8 / Stream 等较新版本可使用 dnf dnf install -y lsof
安装完成后直接执行lsof会列出系统中所有进程打开的全部文件,输出量非常大。默认输出包含七列:COMMAND是进程名,PID是进程号,USER是执行用户,FD表示文件描述符(如cwd表示工作目录,txt表示程序本身,数字加r/w表示读写模式),TYPE是文件类型,DEVICE是设备号,SIZE/OFF是文件大小或偏移量,NODE是inode节点,NAME则是文件路径或端口信息。理解这几列的含义,是后续排查的基础。
按文件和目录定位占用进程
最常见的排查场景是某个文件删不掉,或者想知道是谁在写这个文件。直接以文件路径作为参数即可:
lsof /var/log/nginx/error.log
输出的每一行代表一个持有该文件的进程。如果Nginx有多个worker进程都在写这个日志,会看到多行记录,PID列各不相同。再配合ps -p PID -f就能看到进程的完整启动命令。
如果要排查的是整个目录,比如想知道哪些进程在使用/data目录下的文件,可以加+D参数递归查询:
lsof +D /data
需要注意的是,+D会递归遍历目录下所有子目录,目录层级深、文件多时速度会明显变慢。对性能敏感的场景建议改用+d,它只查看当前层目录,不递归。两者取舍看具体需求:确认整棵目录树被谁占用用+D,只想快速看第一层就用+d。
删除文件后磁盘空间未释放的排查
这是lsof最经典的用途之一。运维中经常遇到这样的情况:用df -h看到磁盘快满了,找到大日志文件后用rm删除,再执行df -h却发现空间一点没释放,而du -sh统计又显示文件确实不在了。
原因在于Linux的文件删除机制:rm只是删除了目录项并减少链接计数,只要还有进程持有该文件的文件描述符,inode就不会真正释放,磁盘空间继续被占用。此时可以用下面这条命令找出所有已删除但仍被占用的文件:
lsof | grep deleted # 输出中 NAME 列带有 (deleted) 标记的,就是被删除但仍占空间的文件
找到对应的PID后有两种处理方式。如果该进程可以重启,直接重启或发送信号让它重新打开日志文件是最干净的办法;如果服务不能中断,可以通过/proc文件系统手动清空文件内容来释放空间:
echo > /proc/进程PID/fd/文件描述符号 # 例如 lsof 输出中 FD 列显示 4w,则执行: echo > /proc/12345/fd/4
这也是为什么生产环境推荐用日志切割工具或logrotate配合copytruncate方案处理日志,而不是直接rm。
端口占用与用户维度的高频用法
启动服务报端口被占用时,用-i参数可以精确定位占用者:
lsof -i:8080 # 查看 8080 端口被哪个进程占用 lsof -i:80,443 # 同时查看多个端口 lsof -i -P -n # 列出所有网络连接,-P 禁止端口名转换,-n 禁止域名解析,速度更快 lsof -i tcp # 只看 TCP 连接 lsof -i udp # 只看 UDP 连接
输出中LISTEN状态表示该进程正在监听此端口,ESTABLISHED表示已建立的连接。确认进程后,用kill PID结束即可释放端口,必要时再用-9强制。
按用户和进程维度查询也很常用,-u指定用户、-p指定进程号、-c按进程名匹配,还可以用逻辑组合:
lsof -u www # 查看用户 www 打开的所有文件 lsof -p 12345 # 查看 PID 为 12345 的进程打开了哪些文件 lsof -c nginx # 查看所有 nginx 进程打开的文件 lsof -u root -c sshd # root 用户且命令名含 sshd 的进程(默认是 AND 关系) lsof -u www -u root # 多个 -u 之间是 OR 关系,查看 www 或 root 打开的文件
另外还有一个容易被忽略的用法:排查挂载点无法卸载的问题。执行umount报device is busy时,用lsof /mnt/data或fuser -vm /mnt/data就能找出占用挂载点的进程,处理完后再卸载即可成功。
排查思路小结
lsof的排查套路可以归纳为四个入口:文件删不掉或想知道谁在写,用lsof 文件路径或+D 目录;删了文件空间不释放,用lsof | grep deleted;端口冲突,用lsof -i:端口号;按人或进程排查,用-u、-p、-c组合过滤。熟练掌握这几个方向,CentOS下绝大多数文件占用类故障都能在几分钟内定位。日常建议养成配合grep、awk过滤的习惯,把lsof的输出限制在关心的范围内,排查效率会更高。