lsof +L1 显示已被删除但仍有进程打开的文件,需通过终止进程或使其释放句柄来清理;可统计占用数、按PID查看详情,并用kill -TERM等安全方式批量处理,辅以日志轮转和监控预防。

lsof +L1 显示的是已被删除但仍有进程打开的文件(即“已删未释放”文件),这些文件仍占磁盘空间,直到对应进程关闭或重启。批量清理的关键不是直接删文件(已删,无法再删),而是终止占用它们的进程或让进程主动释放句柄。
确认哪些进程在占用 (deleted) 文件
先用以下命令查看具体占用情况:
- lsof +L1 | head -20 —— 查看前20条,关注 PID、COMMAND、SIZE 列
- lsof +L1 | awk '{print $2}' | sort | uniq -c | sort -nr —— 统计各 PID 占用数量,找“大户”
- lsof +L1 -p 1234 —— 针对某 PID 查看具体哪些 (deleted) 文件被它持有
安全终止非关键进程(推荐优先尝试)
若确认是日志轮转异常、旧 worker 进程残留等可重启服务,建议发信号让其优雅退出:
- kill -HUP PID —— 对支持重载配置的服务(如 nginx、rsyslog),常触发日志 reopen,自动释放 deleted 句柄
- kill -TERM PID —— 发送终止信号,多数程序会清理后退出
- 避免直接 kill -9,除非确认无状态且无法响应
批量处理脚本(按占用数阈值自动 kill)
以下脚本仅终止占用 ≥5 个 (deleted) 文件的普通用户进程(排除 root 和系统关键进程),执行前请先测试:
#!/bin/bash # lsof_deleted_clean.sh —— 安全清理大量 (deleted) 占用 set -e获取占用 deleted 文件 ≥5 个的非 root、非内核进程 PID(去重)
pids=$(lsof +L1 2>/dev/null | \ awk '$2 ~ /^[0-9]+$/ && $3 != "root" && $1 !~ /^(kthreadd|migration|rcu|watchdog)/ {print $2}' | \ sort | uniq -c | awk '$1 >= 5 {print $2}' | sort -u)
if [ -z "$pids" ]; then echo "No process holding >=5 deleted files found." exit 0 fi
echo "Found PIDs to signal (TERM): $pids" for pid in $pids; do if kill -0 "$pid" 2>/dev/null; then echo "Sending SIGTERM to PID $pid..." kill -TERM "$pid" 2>/dev/null || true sleep 0.3 fi done
等待 2 秒后检查是否释放
sleep 2 remaining=$(lsof +L1 2>/dev/null | wc -l) echo "Remaining deleted-file entries: $remaining"
保存为 lsof_deleted_clean.sh,加执行权限:chmod +x lsof_deleted_clean.sh,运行前建议先加 echo 测试输出。
长期预防建议
- 应用层:确保日志库(如 logrotate 配合 copytruncate 或 postrotate kill -USR1)正确 reopen 日志文件
- 容器环境:检查是否挂载了 host 的 /proc 或 /dev/shm,导致容器内进程误持 host 文件句柄
- 监控项:定期跑 lsof +L1 | wc -l,告警阈值设为 >100
- 运维习惯:服务更新/重启后,顺手检查 lsof +L1 -p $OLD_PID 是否残留










