删了日志文件空间不释放,是因为进程(如Nginx)仍持有已删除文件的打开句柄,内核保留数据块;需用lsof -p PID | grep deleted确认,并通过kill -USR1或nginx -s reopen通知进程重建日志。

为什么删了日志文件,磁盘空间却不释放?
Linux 文件系统中,删除(rm)一个正在被进程打开的文件,只是移除了该文件在目录中的“名字”(即 inode 的硬链接),但只要进程仍持有该文件的打开句柄(file descriptor),内核就会继续保留其数据块在磁盘上。Nginx 主进程和 worker 进程在启动后会以写模式(w 或 ww)持续向 access.log 和 error.log 写入,因此即使你执行 rm /var/log/nginx/access.log,只要 Nginx 没有主动关闭这个 fd,空间就一直被“幽灵文件”占用。
句柄未释放的验证方法
可通过以下命令确认是否为句柄残留导致:
- 查 Nginx 进程 PID:
cat /var/run/nginx.pid或ps aux | grep nginx | grep -v grep - 列出该进程打开的已删除文件:
sudo lsof -p PID | grep deleted
输出中若含类似nginx 12345 www-data 6w REG ... /var/log/nginx/access.log (deleted),说明句柄仍在且文件已被 unlink - 查看对应 fd 的实际路径:
ls -l /proc/PID/fd/6(6 是示例 fd 编号),会显示指向(deleted)的符号链接
Nginx 如何自动重建日志文件?
Nginx 本身不自动重建被删除的日志文件,必须由外部触发。它提供两种机制来“切换”到新文件,本质都是让进程主动关闭旧 fd、重新 open 同名新文件:
-
发送 USR1 信号:主进程收到后,通知所有 worker 关闭当前日志 fd,并重新以相同路径 open 新文件。命令为:
kill -USR1 $(cat /var/run/nginx.pid)或等效的nginx -s reopen -
执行 reload:运行
nginx -s reload也会触发日志 reopen,同时还会重载配置;适合需同步更新配置的场景 - 注意:仅创建空文件(如
touch access.log)不生效——Nginx 不会主动检测文件是否存在,必须显式通知它“换日志”
安全清理与长期运维建议
生产环境应避免直接 rm 日志,推荐组合策略:
- 日常清理优先用清空而非删除:
truncate -s 0 /var/log/nginx/access.log或: > /var/log/nginx/access.log,瞬间释放空间且不中断写入 - 归档时先重命名再 reopen:
mv access.log access.log.$(date +%Y%m%d)→nginx -s reopen,保留历史又确保新日志落盘 - 启用 logrotate 并配好
postrotate脚本,调用kill -USR1,实现全自动轮转(Linux);Windows 下用 PowerShell 脚本 + 任务计划 +nginx -s reopen - 权限需匹配:重建日志文件后,务必
chown和chmod为 Nginx 运行用户(如www-data:adm)及合理权限(如0640)











