运维知识
悠悠
2025年9月14日

这个Linux命令太牛了!lsof让我在生产环境救火无数次

最近在群里看到有小伙伴问,服务器上某个端口被占用了,但是不知道是哪个进程在用,怎么办?还有人说磁盘空间明明删除了大文件,但是df显示空间还是没释放。这些问题其实都可以用一个神器来解决——lsof。

说实话,我刚开始的时候,对lsof这个命令也是一知半解的。记得有一次生产环境出问题,nginx启动不了,报端口被占用,当时我还傻乎乎地用ps aux | grep去找进程,结果找了半天也没找到。后来一个同事过来,直接一个lsof -i:80就把问题定位了(当然ss和netstat也可以),那一刻我才意识到这个命令的强大。

image-20250914220611241

ps:下次面试官问如何查看端口占用的时候,就别只说一个netstat了。还有lsof和ss可以用!!!

lsof到底是什么

lsof的全称是"list open files",翻译过来就是列出打开的文件。但是在Linux系统中,一切皆文件,所以lsof能做的事情远比你想象的要多。网络连接是文件,设备是文件,管道也是文件,所以lsof实际上是一个超级强大的系统诊断工具。

我经常跟新人说,lsof就像是系统的"透视镜",能让你看到系统内部正在发生什么。哪个进程打开了哪些文件,哪个端口被哪个程序占用,哪些文件被删除了但还在被进程使用着,这些信息lsof都能告诉你。

基础用法先搞明白

最简单的用法就是直接输入lsof,不过这样会输出所有打开的文件,信息量太大了,一般我们不会这么用。

lsof

输出的每一行代表一个打开的文件,包含了这些信息:

  • COMMAND:进程名称
  • PID:进程ID
  • USER:用户名
  • FD:文件描述符
  • TYPE:文件类型
  • DEVICE:设备号
  • SIZE/OFF:文件大小或偏移量
  • NODE:inode号
  • NAME:文件名或网络连接信息

刚开始看这些输出可能会觉得眼花缭乱,但是用多了就习惯了。

网络相关的妙用

查看端口占用情况

这个功能我用得最多,特别是在部署新服务的时候。

# 查看80端口被哪个进程占用
lsof -i:80

# 查看所有TCP连接
lsof -i tcp

# 查看所有UDP连接
lsof -i udp

# 查看指定IP和端口的连接
lsof -i@192.168.1.100:22

有一次我们的Redis服务启动不了,报6379端口被占用,但是用systemctl status redis看显示是停止状态的。用lsof -i:6379一查,发现有个僵尸进程还占着端口,kill掉就解决了。

查看网络连接状态

# 查看所有网络连接
lsof -i

# 查看指定状态的连接
lsof -i -sTCP:LISTEN  # 查看监听状态的TCP连接
lsof -i -sTCP:ESTABLISHED  # 查看已建立的TCP连接

这个在排查网络问题的时候特别有用。比如怀疑某个服务连接数过多,就可以用这个命令来确认。

image-20250914221030488

进程相关的用法

查看进程打开的文件

# 查看指定PID打开的文件
lsof -p 1234

# 查看指定进程名打开的文件
lsof -c nginx

# 查看指定用户打开的文件
lsof -u www-data

image-20250914221132841

我记得有次排查一个Java应用内存泄漏的问题,就是用lsof -p查看进程打开的文件数量,发现文件句柄数量一直在增长,最后定位到是代码里没有正确关闭文件流。

查看文件被哪些进程使用

# 查看指定文件被哪些进程打开
lsof /var/log/nginx/access.log

# 查看指定目录下的文件被哪些进程使用
lsof +D /var/log/

这个在你想删除某个文件但是提示文件被占用的时候特别有用。

文件系统相关的神操作

找出被删除但未释放的文件

这个功能简直是救命稻草!经常遇到这种情况:明明删除了大文件,但是df显示磁盘空间没有释放。这通常是因为文件被删除了,但还有进程在使用这个文件。

# 查找被删除但未释放的文件
lsof | grep deleted

# 或者更精确的查找
lsof +L1

有一次我们的服务器磁盘空间告警,我删除了几个GB的日志文件,但是空间还是没释放。用lsof | grep deleted一查,发现有个进程还在往已删除的日志文件里写数据。重启了那个进程,空间立马就释放了。

image-20250914221304484

查看挂载点使用情况

# 查看指定挂载点被哪些进程使用
lsof /mnt/data

# 查看所有挂载点的使用情况
lsof -f -- /dev/sda1

在卸载文件系统的时候,如果提示设备忙,就可以用这个命令找出是哪些进程在使用。

实战案例分享

案例1:解决端口冲突问题

前段时间部署一个新的Web服务,配置的是8080端口,但是启动的时候一直报错说端口被占用。用netstat看了半天也没找到问题。

lsof -i:8080

结果发现是Jenkins占用了这个端口,但是Jenkins配置文件里写的是8081,很奇怪。后来发现是Jenkins的某个插件启动了一个额外的服务占用了8080端口。

案例2:排查文件句柄泄漏

有个Python应用运行一段时间后就会报"Too many open files"的错误。怀疑是文件句柄泄漏。

# 先找到进程PID
ps aux | grep python_app

# 查看进程打开的文件数量
lsof -p 12345 | wc -l

# 查看具体打开了哪些文件
lsof -p 12345

发现进程打开了大量的临时文件,而且数量一直在增长。最后定位到是代码里创建临时文件后没有正确清理。

案例3:磁盘空间异常问题

服务器磁盘使用率突然飙升到95%,但是找不到大文件。后来用lsof发现有个日志轮转脚本有问题。

# 查找大文件
lsof | awk '$7 ~ /^[0-9]+$/ && $7 > 1000000 {print $2, $7, $9}' | sort -k2 -nr

发现有个进程打开了一个几GB的文件,但是这个文件在文件系统里找不到,原来是被删除了但进程还在写入。

高级用法和技巧

组合条件查询

lsof支持多种条件的组合,默认是OR关系,可以用-a参数改为AND关系。

# 查看用户www-data打开的网络连接(OR关系)
lsof -u www-data -i

# 查看用户www-data打开的网络连接(AND关系)
lsof -a -u www-data -i

输出格式控制

# 不显示主机名,直接显示IP
lsof -n -i

# 不显示端口名,直接显示端口号
lsof -P -i

# 组合使用
lsof -nP -i:80

这个在脚本里特别有用,因为解析主机名和端口名会比较慢。

持续监控

# 每2秒刷新一次
lsof -r 2 -i:80

# 监控到没有输出就退出
lsof +r 1 -i:80

这个功能在调试网络连接问题的时候很有用,可以实时看到连接的变化。

性能优化小贴士

lsof虽然强大,但是在大型系统上运行可能会比较慢,特别是不加任何参数的时候。有几个优化技巧:

  1. 尽量使用具体的参数,避免全量扫描
  2. 使用-n和-P参数避免DNS和端口名解析
  3. 在脚本中使用时,考虑缓存结果
# 这样比较快
lsof -nP -i:80

# 这样会很慢
lsof | grep :80

常见问题和注意事项

使用lsof的时候有几个坑需要注意:

  1. 权限问题:有些信息需要root权限才能看到
  2. 系统负载:在高负载系统上运行lsof可能会影响性能
  3. 输出解读:要理解各个字段的含义,特别是FD字段

FD字段的含义比较复杂:

  • cwd:当前工作目录
  • txt:程序代码
  • mem:内存映射文件
  • 数字:文件描述符号
  • r、w、u:读、写、读写模式

与其他工具的配合

lsof经常需要和其他工具配合使用:

# 配合ps使用
lsof -p $(pgrep nginx)

# 配合netstat对比
netstat -tlnp | grep :80
lsof -i:80

# 配合awk处理输出
lsof -i | awk '/ESTABLISHED/ {print $2}' | sort | uniq -c

我个人比较喜欢把lsof和其他工具组合起来写成小脚本,这样排查问题的时候效率会高很多。

总结

lsof真的是一个被低估的神器,掌握了它基本上可以解决大部分文件和网络相关的问题。从端口占用到文件句柄泄漏,从磁盘空间异常到网络连接排查,lsof都能派上用场。

当然,工具只是工具,关键还是要理解系统的工作原理。lsof能告诉你现象,但是要分析出根本原因,还是需要对系统有深入的理解。

记住,运维这个工作很多时候就是在和时间赛跑,系统出问题的时候,每一分钟的延迟都可能造成巨大的损失。而lsof这样的工具,就是你手中最锐利的武器。不过话说回来,再好的工具也需要不断的实践才能真正掌握。我建议大家可以在自己的测试环境里多折腾折腾,比如故意制造一些端口冲突、文件句柄泄漏的场景,然后用lsof来排查。这样真正遇到问题的时候,你就不会手忙脚乱了。

最后想说的是,lsof的输出信息比较敏感,包含了很多系统内部的信息。在分享排查过程或者截图的时候,记得做好脱敏处理,避免泄露重要的系统信息。

如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!

公众号:运维躬行录

个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码