必须加sudo才能查到root或其他用户进程占用的文件,因普通用户无权读取其/proc/pid/fd目录;路径须绝对且精确,软链接需加-l参数;fd列中reg+w/u表示正在写入,cwd仅表示当前工作目录;name含(deleted)说明文件已删但句柄未关。

直接用 lsof /path/to/file,但几乎每次都要加 sudo,否则看不到 root 或其他用户进程的打开状态。
查单个文件被谁打开:路径必须完整且加 sudo
普通用户运行 lsof /var/log/syslog 经常返回空——不是没进程在用,而是你没权限读取其他用户的 /proc/PID/fd/。真实场景下,日志、设备节点、socket 文件基本都由 root 或服务用户(如 www-data)持有。
- 必须写绝对路径:
lsof ./config.yaml无效,得写lsof /home/user/app/config.yaml - 软链接默认不跟随;若目标是链接指向的真实文件,加
-L参数:sudo lsof -L /etc/nginx/conf.d -
FD列看到cwd表示该进程当前工作目录是这个路径,未必真在读写它;REG+w或u才说明正在写入 - NAME 列末尾带
(deleted),说明文件已被rm但进程还握着 fd,磁盘空间不会释放
查不到结果?优先检查权限和路径精度
常见“明明在写却查不到”的情况,90% 是权限或路径问题,不是工具失效。
- 先试
sudo lsof /path/to/file—— 这是最关键一步,别跳过 - 确认路径是否被 bind mount 或 overlayfs 隐藏;
lsof查的是内核实际打开的路径,不是你ls看到的表层路径 - 如果文件刚被
mv或cp --reflink操作过,可能 inode 已变,旧路径查不到,得按新路径重试 -
fuser /path/to/file不推荐用于单文件排查——它对普通文件识别率低,常漏掉vim、tail -f这类行为
查目录或已删文件:用 +d 和 +L1 而不是 grep 全局扫
想看整个 /var/log 下哪些文件正被占用,或者磁盘 df 满了但 du 算不出大文件,这两个选项比 lsof | grep 快、准、安全得多。
-
sudo lsof +d /var/log:递归扫描该目录及子目录所有被打开的文件,不跨挂载点(比如/var/log/journal是独立挂载的,得单独跑一次) -
sudo lsof +L1:只列出 link count 为 0 的文件,即已unlink但未close的句柄,NAME 列明确标(deleted) - 避免
lsof | grep filename:全系统扫描 fd 开销大,且会误匹配路径片段(比如/opt/app/logs和/opt/app-legacy/logs都会被命中) - 输出太长时加
| awk '{print $1,$2,$9}'只留 COMMAND、PID、NAME,快速定位
没有 lsof 怎么办?直接翻 /proc/PID/fd
某些最小化系统或容器里没装 lsof,但 /proc 是内核原生接口,永远可用。
- 先用
ps aux | grep keyword或pgrep -f nginx找 PID - 再执行
ls -l /proc/1234/fd/ | grep your_file—— 注意这里能看见(deleted)标记,也能看到 fd 编号(比如7) - 用
readlink /proc/1234/fd/7确认该 fd 指向的真实路径,包括符号链接展开后的位置 - 这个方法不能反向查(给路径找 PID),只能在你知道 PID 后验证,但它不依赖任何外部命令
真正容易被忽略的是:很多“占用”其实只是 cwd 或 txt(执行文件),并非持续读写;而 (deleted) 状态的文件,kill 掉对应进程才是唯一释放空间的办法——改名、touch、chown 都没用。











