你最常用的一个 Linux 命令是什么?为什么?
你最常用的一个 Linux 命令是什么?为什么?
如果只推荐一个在日常排查故障时起关键作用,且最能体现 Linux “一切皆文件”设计哲学的命令,那一定是 lsof(List Open Files)。
在日常开发与系统运维中,遇到诸如端口占用、磁盘空间释放异常(删了文件但空间没降)、或者设备卸载报错(device is busy)等问题时,使用 lsof 往往能快速定位原因。
一、 磁盘空间已删除但未释放的“幽灵文件”
我们之前遇到过一次典型的线上磁盘告警:df -h 显示系统盘占用 100%,导致部分写盘操作失败;但进到目录下执行 du -sh *,所有可见文件大小加起来也才 20GB,剩下的 80GB 空间下落不明。
在没有明确原因时,直接重启生产服务器显然不是合理的方案。通过执行以下命令:
sudo lsof | grep deleted
输出中可以看到,一个已被 rm 删除的访问日志文件(access.log (deleted)),其对应的文件描述符(FD)依然被 Nginx 主进程持有,且大小显示为 80GB。
在 Linux 中,删除文件(rm)实际上只是移除了该文件的目录项(Dentry),使其链接数减一。如果此时还有进程打开着该文件,那么对应的 inode 节点的引用计数并不为零,磁盘空间便不会被释放。该文件在系统里依然占用物理扇区,直到持有它的进程关闭该文件描述符或退出。
定位到 PID 后,直接执行 nginx -s reload 让进程重载配置并释放旧的文件句柄,磁盘空间随即正常释放。
二、 端口占用排查
服务启动时如果报错 Bind failed: Address already in use,说明端口已被其他进程占用。相比于 netstat,使用 lsof 能更直接地定位到目标进程:
lsof -i :8080
该命令可以直接输出占用端口的进程名称(COMMAND)、进程号(PID)和用户(USER),从而能够直接根据 PID 终止冲突进程。
三、 挂载目录繁忙(device is busy)的排查
在卸载挂载的分区(umount)时,系统经常会提示 device is busy,这表明有进程或终端处于该目录下,或者有文件处于读写状态。执行以下命令可以列出占用该目录的所有进程:
lsof /mnt/data
获取相关进程后,只需退出对应的终端路径或终止读写进程,即可顺利卸载目录。
四、 观察指定进程打开的文件句柄
在排查文件描述符泄漏(File Descriptor Leak)或分析特定程序行为时,通过 lsof -p <PID> 可以列出该进程当前打开的所有文件资源:包括加载的共享库(.so 文件)、TCP/UDP 网络连接、日志文件以及系统管道。这能直观地展示进程对系统资源的占用情况。
五、 生产环境使用注意事项
最后,分享几个在生产环境使用 lsof 时需要注意的细节:
- 高并发高负载服务器上慎用不带过滤条件的
lsof。如果直接执行lsof,它会扫描整个系统的/proc目录,列出所有打开的文件描述符。在极其繁忙、打开文件数超百万的数据库服务器上,这会导致命令执行极慢,甚至短暂消耗大量 CPU 资源。执行时务必带上具体的过滤条件(如-p、-i或文件名)。 - 注意权限限制。普通用户运行
lsof只能看到自己拥有的进程打开的文件。排查系统级故障或他人进程的资源占用时,必须使用sudo lsof,否则会漏掉关键信息。 - 不要用它替代专门的性能监控工具。
lsof展现的是静态的当前状态。如果需要监控系统长期的磁盘 I/O 繁忙程度,应该去用iostat;如果需要抓取实时的网络流量包,应该用tcpdump。把lsof定位在“快速故障定位”和“资源占用排查”的场景,才是它的最佳使用方式。
总结
作为 Linux 系统下的常用工具,lsof 的核心价值在于它将 Unix “一切皆文件”的设计哲学具象化。在处理文件占用、句柄泄漏和端口冲突等运维开发痛点时,它能够提供最直接的线索。理解它背后的文件系统运行逻辑,是高效使用它的关键。
