Linux lsof 完整指南 - 从端口冲突排查到释放已删除文件磁盘空间的核心实战技巧

概述

在 Linux 系统运维过程中遇到的“端口冲突”或“删除文件后磁盘空间未释放”等问题,可以通过 lsof 命令迅速得到解决。本文将深入探讨在“一切皆文件”的 Linux 环境下,如何将 lsof 应用于实际生产中的核心技巧。从端口追踪到文件锁释放,逐步解析系统工程师必备的故障排查实用经验。

lsof 基本检查及查看特定用户/进程打开的文件

检查系统中是否已安装 lsof 命令,如果未安装,则执行 command -v lsof >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y lsof) 命令以安装软件包。

command -v lsof >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y lsof)

执行 lsof -v 命令以查看 lsof 命令的安装版本及构建信息。
⚙️ [主要选项]

-u : 查询特定用户账户打开的文件和进程列表。
-c : 过滤以指定进程名称开头的进程所打开的文件列表。
-p : 查看特定进程 ID (PID) 打开的文件列表。
-i : 查询使用网络套接字和特定端口的进程。
+D : 递归搜索指定目录及其子路径下打开的文件列表。
-t : 仅精简输出进程 ID (PID),每行一个,便于与脚本集成。

lsof -v

执行 mkdir -p /tmp/lsof_lab && echo '테스트 파일 내용' > /tmp/lsof_lab/sample.txt 命令,准备用于 lsof 实操演练的测试目录和示例文件。

mkdir -p /tmp/lsof_lab && echo ‘테스트 파일 내용’ > /tmp/lsof_lab/sample.txt

为了让进程持续占用刚创建的示例文件,在后台执行 tail -f /tmp/lsof_lab/sample.txt & 命令进行跟踪。

tail -f /tmp/lsof_lab/sample.txt &

lsof -u $(whoami) | head -n 15 命令用于查询当前登录用户运行的进程所占用的文件列表(显示前 15 行)。
可以查看基础系统库和可执行文件等当前账户正在打开的文件的详细信息。

lsof -u $(whoami) | head -n 15

lsof -c tail 命令用于搜索并输出进程名为 tail 的进程所打开的文件和库列表。
通过该命令可以查看在后台运行的 tail 命令正在引用哪些文件描述符和共享库。

lsof -c tail

完成演练后,执行 killall tail 2>/dev/null || true 命令以安全终止并清理在后台运行的 tail 进程。

killall tail 2>/dev/null || true

网络端口检查与进程冲突排查

为了搭建端口检查及进程冲突的实操环境,检查系统是否已安装 python3,若未安装则安装该软件包。

command -v python3 >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y python3)

在后台启动一个监听 8080 端口的简易 Web 服务器,用于测试网络端口占用情况。

python3 -m http.server 8080 >/dev/null 2>&1 &

等待 1 秒,直到后台启动的 Web 服务器进程成功绑定到 8080 端口。

sleep 1

lsof -i :8080 命令用于查询正在使用 8080 端口的进程。
通过输出结果可以确认,PID 为 371 的 python3 进程正在 8080 端口上处于 LISTEN 状态。

lsof -i :8080

lsof -i -P -n | head -n 15 命令直接以数字形式快速输出系统的网络套接字列表,而不进行端口号和服务名称或 IP 地址与主机名的转换。
由于跳过了 DNS 反向解析和服务端口名称映射过程,因此可以无延迟地迅速掌握端口占用情况。

lsof -i -P -n | head -n 15

lsof -i TCP:8080 -sTCP:LISTEN 命令可以精确定位并仅输出 8080 端口中处于 TCP 协议及 LISTEN 状态的连接。
在排除多余的会话连接、准确定位正在该端口上监听连接的守护进程时非常实用。

lsof -i TCP:8080 -sTCP:LISTEN

完成演练后,强制终止占用 8080 TCP 端口的后台 Web 服务器进程,以清理被占用的资源。

fuser -k 8080/tcp 2>/dev/null || kill $(lsof -t -i :8080) 2>/dev/null || true

追踪特定目录及阻止卸载的文件 (Device Busy)

为了复现目录被占用以及阻止卸载的情况,创建实操测试目录并切换至该路径。

mkdir -p /tmp/mount_test && cd /tmp/mount_test

执行 echo '작업 중인 파일' > active_work.log 命令,创建供进程访问的目标日志文件。

echo ‘작업 중인 파일’ > active_work.log

在后台运行 sleep 进程,将创建的文件作为标准输入引用并持续占用。

sleep 30 < active_work.log &

切换工作路径至用户主目录,以便从被占用的目录外部检查状态。

cd /root || cd ~

lsof +D /tmp/mount_test 命令用于递归追踪并输出指定目录及其子路径下打开的所有文件和进程。
通过输出结果可以确认,PID 为 450 的 sleep 进程将该目录作为当前工作目录 (cwd) 引用,并且以只读模式 (0r) 打开了 active_work.log 文件,这正是导致无法卸载的原因。

lsof +D /tmp/mount_test

完成演练后,安全终止占用目录和文件的后台 sleep 进程。

killall sleep 2>/dev/null || true

删除演练中使用的临时测试目录及其子文件,清理系统资源。

rm -rf /tmp/mount_test

恢复与清理已删除但仍占用磁盘空间的幽灵文件 (deleted)

为了测试磁盘空间泄漏,创建实操测试目录并生成一个大小为 10MB 的大型测试文件。

mkdir -p /tmp/leak_test && dd if=/dev/zero of=/tmp/leak_test/large.img bs=1M count=10 >/dev/null 2>&1

在后台进行跟踪,让进程继续保持对该大文件的句柄占用。

tail -f /tmp/leak_test/large.img &

在文件系统中强制删除该被占用的大文件,以复现幽灵文件导致的空间泄漏场景。

rm -f /tmp/leak_test/large.img

lsof | grep '(deleted)' | head -n 5' 命令用于查询在文件系统中已被删除但仍被进程打开而占用磁盘空间的文件列表。
通过该命令可以迅速找出即使执行了 rm 命令但磁盘空间依然未被释放的幽灵文件及其对应进程。

lsof | grep ‘(deleted)’ | head -n 5

基于通过 lsof -t 提取的进程 ID,查看 /proc/$TARGET_PID/fd/ 目录下的文件描述符列表。
通过直接确认进程引用的文件描述符编号,无需重启进程即可清空文件释放空间,或在必要时通过该文件描述符恢复已删除的原始数据。

TARGET_PID=$(lsof -t /tmp/leak_test/large.img 2>/dev/null | head -n 1) && [ -n “$TARGET_PID” ] && ls -l /proc/$TARGET_PID/fd/ || true

完成演练后,安全终止继续占用幽灵文件的后台进程,彻底释放并收回磁盘空间。

killall tail 2>/dev/null || true

彻底删除演练中使用的临时测试目录,清理系统资源。

rm -rf /tmp/leak_test

至此,我们简要了解了利用 lsof 命令从解决端口冲突到释放已删除文件磁盘空间的核心实战技巧。
希望本文整理的内容能够在实际服务器运维与故障排查过程中为大家提供帮助。