“DEL”状态表示文件已被删除但进程仍持有句柄,常见于热更新场景;lsof -p 默认不显示dlopen加载的.so,因未占用FD,应查/proc/PID/maps;权限不足时需sudo,否则结果不全。

lsof -p 显示的“DEL”状态代表什么
执行 lsof -p <PID> 时,如果某行 TYPE 列显示为 DEL(如 DEL、DEL (deleted)),说明该动态库文件已被进程打开但其磁盘上的 inode 已被 unlink —— 即文件被删除,但进程仍持有句柄。常见于热更新场景(如 Nginx reload、Java 应用更新 lib 后未重启)。此时 lsof 仍能列出路径,但实际文件已不可访问,ls -l /proc/<PID>/fd/<FD> 会显示 (deleted)。
为什么 lsof -p 看不到某些 .so 文件
lsof -p 默认只显示进程当前打开的文件描述符(FD),而动态库加载(尤其是 dlopen)可能不占用常规 FD,或使用 MAP_DENYWRITE 映射后关闭了底层 fd。此时它不会出现在 lsof 输出中。更可靠的方式是查 /proc/<PID>/maps:
- 运行
grep '\.so' /proc/<PID>/maps,可看到所有内存映射的共享库及其权限(如r-xp表示可读可执行) - 配合
awk '{print $6}'提取路径,再用sort -u去重 - 注意:部分库路径为
[anon]或[stack],说明是匿名映射或内核模块,不是用户态 .so
对比 readelf、ldd 和 /proc/PID/maps 的适用场景
ldd 只反映**可执行文件或共享库自身的静态依赖声明**,不体现运行时实际加载的库(比如 dlopen("libfoo.so") 不会出现在 ldd 结果里);readelf -d 同理,只看 ELF 的 DT_NEEDED 条目。而 /proc/<PID>/maps 是唯一能反映真实运行时加载状态的来源。
- 要查「启动时硬依赖」→ 用
ldd /proc/<PID>/exe - 要查「运行时 dlopen 加载」→ 必须看
/proc/<PID>/maps+grep '\.so' - 要确认某个 .so 是否真被映射 → 在
/proc/<PID>/maps中搜完整路径,注意可能有版本号或软链接展开差异
用 lsof -p 查动态库时容易忽略的权限问题
lsof -p 需要读取目标进程的 /proc/<PID>/fd/ 目录,若当前用户非 root 且非进程所有者,会因权限不足跳过大部分条目(仅显示自己有权限访问的 fd),导致漏掉关键 .so。此时输出可能为空或只有少量结果,但不代表没加载库。
- 普通用户执行
lsof -p <PID>报permission denied是常态,不是命令写错 - 必须用
sudo lsof -p <PID>才能获得完整视图 - 即使有 root 权限,某些容器化环境(如 PID namespace 隔离)下
/proc/<PID>路径可能不可见,需进容器命名空间执行
/proc/<PID>/maps;lsof -p 只是辅助手段,且高度依赖权限和加载方式。别在没 sudo 的情况下信它的输出。


















