最近在群里看到有小伙伴问,服务器上某个端口被占用了,但是不知道是哪个进程在用,怎么办?还有人说磁盘空间明明删除了大文件,但是df显示空间还是没释放。这些问题其实都可以用一个神器来解决——lsof。
说实话,我刚开始的时候,对lsof这个命令也是一知半解的。记得有一次生产环境出问题,nginx启动不了,报端口被占用,当时我还傻乎乎地用ps aux | grep去找进程,结果找了半天也没找到。后来一个同事过来,直接一个lsof -i:80就把问题定位了(当然ss和netstat也可以),那一刻我才意识到这个命令的强大。
image-20250914220611241image-20250914220611241
ps:下次面试官问如何查看端口占用的时候,就别只说一个netstat了。还有lsof和ss可以用!!!
lsof到底是什么lsof的全称是"list open files",翻译过来就是列出打开的文件。但是在Linux系统中,一切皆文件,所以lsof能做的事情远比你想象的要多。网络连接是文件,设备是文件,管道也是文件,所以lsof实际上是一个超级强大的系统诊断工具。
我经常跟新人说,lsof就像是系统的"透视镜",能让你看到系统内部正在发生什么。哪个进程打开了哪些文件,哪个端口被哪个程序占用,哪些文件被删除了但还在被进程使用着,这些信息lsof都能告诉你。
基础用法先搞明白最简单的用法就是直接输入lsof,不过这样会输出所有打开的文件,信息量太大了,一般我们不会这么用。
代码语言:javascript代码运行次数:0运行复制lsof输出的每一行代表一个打开的文件,包含了这些信息:
• COMMAND:进程名称• PID:进程ID• USER:用户名• FD:文件描述符• TYPE:文件类型• DEVICE:设备号• SIZE/OFF:文件大小或偏移量• NODE:inode号• NAME:文件名或网络连接信息刚开始看这些输出可能会觉得眼花缭乱,但是用多了就习惯了。
网络相关的妙用查看端口占用情况这个功能我用得最多,特别是在部署新服务的时候。
代码语言:javascript代码运行次数:0运行复制# 查看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掉就解决了。
查看网络连接状态代码语言:javascript代码运行次数:0运行复制# 查看所有网络连接
lsof -i
# 查看指定状态的连接
lsof -i -sTCP:LISTEN # 查看监听状态的TCP连接
lsof -i -sTCP:ESTABLISHED # 查看已建立的TCP连接这个在排查网络问题的时候特别有用。比如怀疑某个服务连接数过多,就可以用这个命令来确认。
image-20250914221030488image-20250914221030488
进程相关的用法查看进程打开的文件代码语言:javascript代码运行次数:0运行复制# 查看指定PID打开的文件
lsof -p 1234
# 查看指定进程名打开的文件
lsof -c nginx
# 查看指定用户打开的文件
lsof -u www-dataimage-20250914221132841image-20250914221132841
我记得有次排查一个Java应用内存泄漏的问题,就是用lsof -p查看进程打开的文件数量,发现文件句柄数量一直在增长,最后定位到是代码里没有正确关闭文件流。
查看文件被哪些进程使用代码语言:javascript代码运行次数:0运行复制# 查看指定文件被哪些进程打开
lsof /var/log/nginx/access.log
# 查看指定目录下的文件被哪些进程使用
lsof +D /var/log/这个在你想删除某个文件但是提示文件被占用的时候特别有用。
文件系统相关的神操作找出被删除但未释放的文件这个功能简直是救命稻草!经常遇到这种情况:明明删除了大文件,但是df显示磁盘空间没有释放。这通常是因为文件被删除了,但还有进程在使用这个文件。
代码语言:javascript代码运行次数:0运行复制# 查找被删除但未释放的文件
lsof | grep deleted
# 或者更精确的查找
lsof +L1有一次我们的服务器磁盘空间告警,我删除了几个GB的日志文件,但是空间还是没释放。用lsof | grep deleted一查,发现有个进程还在往已删除的日志文件里写数据。重启了那个进程,空间立马就释放了。
image-20250914221304484image-20250914221304484
查看挂载点使用情况代码语言:javascript代码运行次数:0运行复制# 查看指定挂载点被哪些进程使用
lsof /mnt/data
# 查看所有挂载点的使用情况
lsof -f -- /dev/sda1在卸载文件系统的时候,如果提示设备忙,就可以用这个命令找出是哪些进程在使用。
实战案例分享案例1:解决端口冲突问题前段时间部署一个新的Web服务,配置的是8080端口,但是启动的时候一直报错说端口被占用。用netstat看了半天也没找到问题。
代码语言:javascript代码运行次数:0运行复制lsof -i:8080结果发现是Jenkins占用了这个端口,但是Jenkins配置文件里写的是8081,很奇怪。后来发现是Jenkins的某个插件启动了一个额外的服务占用了8080端口。
案例2:排查文件句柄泄漏有个Python应用运行一段时间后就会报"Too many open files"的错误。怀疑是文件句柄泄漏。
代码语言:javascript代码运行次数:0运行复制# 先找到进程PID
ps aux | grep python_app
# 查看进程打开的文件数量
lsof -p 12345 | wc -l
# 查看具体打开了哪些文件
lsof -p 12345发现进程打开了大量的临时文件,而且数量一直在增长。最后定位到是代码里创建临时文件后没有正确清理。
案例3:磁盘空间异常问题服务器磁盘使用率突然飙升到95%,但是找不到大文件。后来用lsof发现有个日志轮转脚本有问题。
代码语言:javascript代码运行次数:0运行复制# 查找大文件
lsof | awk '$7 ~ /^[0-9]+$/ && $7 > 1000000 {print $2, $7, $9}' | sort -k2 -nr发现有个进程打开了一个几GB的文件,但是这个文件在文件系统里找不到,原来是被删除了但进程还在写入。
高级用法和技巧组合条件查询lsof支持多种条件的组合,默认是OR关系,可以用-a参数改为AND关系。
代码语言:javascript代码运行次数:0运行复制# 查看用户www-data打开的网络连接(OR关系)
lsof -u www-data -i
# 查看用户www-data打开的网络连接(AND关系)
lsof -a -u www-data -i输出格式控制代码语言:javascript代码运行次数:0运行复制# 不显示主机名,直接显示IP
lsof -n -i
# 不显示端口名,直接显示端口号
lsof -P -i
# 组合使用
lsof -nP -i:80这个在脚本里特别有用,因为解析主机名和端口名会比较慢。
持续监控代码语言:javascript代码运行次数:0运行复制# 每2秒刷新一次
lsof -r 2 -i:80
# 监控到没有输出就退出
lsof +r 1 -i:80这个功能在调试网络连接问题的时候很有用,可以实时看到连接的变化。
性能优化小贴士lsof虽然强大,但是在大型系统上运行可能会比较慢,特别是不加任何参数的时候。有几个优化技巧:
1. 尽量使用具体的参数,避免全量扫描2. 使用-n和-P参数避免DNS和端口名解析3. 在脚本中使用时,考虑缓存结果代码语言:javascript代码运行次数:0运行复制# 这样比较快
lsof -nP -i:80
# 这样会很慢
lsof | grep :80常见问题和注意事项使用lsof的时候有几个坑需要注意:
1. 权限问题:有些信息需要root权限才能看到2. 系统负载:在高负载系统上运行lsof可能会影响性能3. 输出解读:要理解各个字段的含义,特别是FD字段FD字段的含义比较复杂:
• cwd:当前工作目录• txt:程序代码• mem:内存映射文件• 数字:文件描述符号• r、w、u:读、写、读写模式与其他工具的配合lsof经常需要和其他工具配合使用:
代码语言:javascript代码运行次数:0运行复制# 配合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的输出信息比较敏感,包含了很多系统内部的信息。在分享排查过程或者截图的时候,记得做好脱敏处理,避免泄露重要的系统信息。