第 6 章 · 07 资源归属排查: 本节摘要: (list open files)是排查「端口被谁占了」「文件被谁锁了删不掉」「某进程打开了哪些东西」的万能工具。它的底层基础是第 1 章讲过的「文件描述符」——在 Linux 里,不仅普通文件是 fd,网络套接字、管道、设备也都是 fd,所以 能列出进程打开的「一切」。本节要讲清它的三个高频用法( 查端口、 查目录占用、 查某进程),以及它背后的文件描述符概念。 内容来源:原项目「Linux 命令大全」 ,精选并套用体系化模板。 学习目标 阅读完本节,你应当能够: 说清「文件描述符(fd)」是进程与「一切资源」之间的句柄,fd 0/1/2 是标准流。 解释为什么 既能查文件、又能查网络端口(因为在 Linux 里套接字也是一种 fd)。
lsof本节摘要:
lsof(list open files)是排查「端口被谁占了」「文件被谁锁了删不掉」「某进程打开了哪些东西」的万能工具。它的底层基础是第 1 章讲过的「文件描述符」——在 Linux 里,不仅普通文件是 fd,网络套接字、管道、设备也都是 fd,所以lsof能列出进程打开的「一切」。本节要讲清它的三个高频用法(lsof -i :80查端口、lsof +D /path查目录占用、lsof -p PID查某进程),以及它背后的文件描述符概念。
内容来源:原项目「Linux 命令大全」
command/lsof.md,精选并套用体系化模板。
阅读完本节,你应当能够:
lsof 既能查文件、又能查网络端口(因为在 Linux 里套接字也是一种 fd)。lsof -i :端口 排查「端口被谁占」。lsof +D /路径 或 lsof 文件路径 排查「文件被谁锁着删不掉」。lsof -p PID 查某个进程打开了哪些资源(排查资源泄漏)。lsof 的根基第 1 章讲过,每个进程有一张「文件描述符表」,记录它打开的资源。fd 0/1/2 是标准流(stdin/stdout/stderr),从 3 开始是进程自己打开的。
Linux 的「一切皆文件」哲学意味着,不仅普通文件是 fd,这些也都是 fd:
| 建的)/dev/null、终端 /dev/pts/0)lsof 做的事就是:遍历所有进程的 fd 表,列出「谁打开了什么」。因为套接字也是 fd,所以 lsof 能查「端口被谁占」;因为打开的文件是 fd,所以能查「这个文件被谁锁着」。
进程 PID 1234 的 fd 表: fd 0 -> /dev/pts/0 (stdin, 你的终端) fd 1 -> /dev/pts/0 (stdout) fd 2 -> /dev/pts/0 (stderr) fd 3 -> /var/log/app.log (它打开的日志文件) fd 4 -> TCP *:80 (它监听 80 端口) lsof 把这张表列出来, 你就能看到"1234 占了 80 端口"
lsof -i :80 # 谁在监听/连接 80 端口 lsof -i :8080 # 查 8080 lsof -iTCP -sTCP:LISTEN # 列出所有 TCP 监听 lsof -i @192.168.1.10 # 与某 IP 的连接
这是排查「Address already in use(端口被占)」的标准手段。-i 表示按网络地址过滤,:80 指端口号。
💡 技巧:
lsof -i :端口找到占用的进程后,记下 PID,用第 04 节的kill处理。整个流程是「端口冲突 → lsof 找 PID → kill 杀掉」。
lsof /var/log/app.log # 这个文件被哪些进程打开 lsof +D /mnt/usb # /mnt/usb 目录下被打开的文件(用 +D 递归)
经典场景:删文件时报「device is busy」或 umount 报错,用 lsof +D /mnt/usb 找出谁还在用这个目录的文件,关掉那个进程就能卸载了。
lsof -p 1234 # 进程 1234 打开了哪些 fd lsof -p 1234 2>/dev/null | wc -l # 数它开了多少个 fd(排查 fd 泄漏)
应用场景:怀疑某程序「文件描述符泄漏」(打开文件不关闭,fd 数不断涨,最终耗尽 Too many open files),用 lsof -p PID | wc -l 监控它的 fd 数变化。
lsof 查不到某些进程(权限)lsof -i :80 # 普通用户可能看不到别人的进程 sudo lsof -i :80 # 用 sudo 才能看全(尤其是别人/root 的进程)
lsof 只能看到自己有权限看的进程。排查系统级端口/服务占用,通常需要 sudo。
lsof +D 在大目录上很慢+D 是递归遍历目录下所有文件,目录很大时很慢。替代:lsof +d /path(只看一层)或先 fuser /path(更快但信息少)。
第 2 章讲过这个坑:删了文件但空间没回收,因为有进程还持有它的 fd。用 lsof 找出这个进程:
lsof | grep deleted # 找"已删除但仍被打开"的文件 # 看到 PID 后, 重启或 reload 那个进程, 它释放 fd 后空间立刻回收
lsof 列出的这类文件,STATE 列会标 deleted,表示「文件名已删,但 fd 还开着」。这是排查「删文件不释放空间」的终极手段。
ss/fuser查端口用 ss -tlnp(第 7 章)有时更快更现代;查文件占用 fuser /path 是轻量替代。lsof 信息最全但稍重,按需选择。
lsof 的根基是「文件描述符(fd)」——在 Linux,文件/套接字/管道/设备都是 fd,所以 lsof 能查「一切资源」。lsof -i :端口(查端口被谁占)、lsof 文件或 +D 目录(查被谁锁着)、lsof -p PID(查某进程开了什么)。lsof | grep deleted 找到还持有 fd 的进程,重启它即可回收。ss/fuser 是更轻量的替代工具。下一节讲「最后救命」的终极排查工具——strace,它打印进程的每个系统调用,是所有常规手段失效时的手术刀。