Linux 日志轮转后磁盘空间没释放:用 失联文件句柄定位并恢复
凌晨值班运维最常碰到这种完全不合预期的磁盘告警:df -h /var 显示使用率已经冲到92%,但切到日志目录敲完 du -sh /var/log 算出来的总容量才几十GB。明明刚跑完logrotate,旧日志文件早就不在目录里了,占用的磁盘空间就是没释放出来。
这种情况别急着随手删别的文件腾空间。Linux的机制里,只要进程还握着对应文件的描述符,就算文件已经从文件夹里删掉了,进程还是能正常读写它,文件占的磁盘块就完全不会被回收。标准排查路径很清晰:先核对文件系统的统计差额,再找出带 失联 标记的持句柄进程,最后按照业务特性选 reload、受控重启,或者等journald完成自身轮转就行。
碰到这种日志删完空间不释放的场景,不用额外找冷门工具,顺着文件描述符链路走,10分钟内就能准确定位到占空间的失联文件,不会误操作影响线上业务。
df的统计结果明显比日志目录的du大,就是要排查失联文件句柄的明确信号,别上来就直接删整个目录。lsof +L1可以优先筛选出硬链接数小于1的已删除文件,重点关注输出里的COMMAND、PID、FD和SIZE/OFF几列。- 释放空间的核心是让持有句柄的进程主动关闭文件;对着已经失联的文件路径再删多少次都没用。
- 服务管理器 journal要区分开活跃日志和归档日志,必要时先
journalctl --rotate再执行vacuum清理操作。
先把 df、du 的差额拆出来
第一步只做观察操作,完全不动线上服务。先确认告警对应的挂载点,别把根分区、容器overlay存储或者独立数据盘的统计搞混:df -hT /var、du -xhd1 /var 2>/dev/null | sort -h、du -xhd1 /var/log 2>/dev/null | sort -h。
df 统计的是整个文件系统已经分配出去的磁盘块,du 是遍历目录树统计当前还能直接看到的文件总大小。两者差值很大的时候,除了失联文件之外,还要排查挂载点遮挡、未销毁的容器层,还有文件系统本身预留的空间。要是 /var/log 统计的目录总大小只有18G,而 df 显示已用空间比预期多了30G,接着查未释放的文件句柄,比反复跑清理命令要高效得多。

看统计数字时别忽略文件系统类型
df -hT 的类型列很关键。XFS、ext4还有容器的overlay存储,后续的排查细节差别不小;如果目标目录落在别的独立挂载点上,加 du -x 参数能避免把其他文件系统的占用算进来。这个阶段的唯一目标,就是确认「可见目录总大小」和「文件系统已用总量」确实存在明确差值。
用 lsof 找到仍在写入的失联文件
在Linux主机上,先用最精准的筛选条件定位已删除但仍被进程打开的文件:sudo lsof +L1,定位到大致范围后再用 sudo lsof -nP +L1 | grep -E '/var/log|/run/log|失联' 进一步缩小排查范围。
输出结果里重点看四列:COMMAND 是进程名,PID 是进程ID,FD 是对应的文件描述符,SIZE/OFF 可以快速判断哪个持有的失联文件占用空间最大。典型的输出结果类似 nginx 1842 www-data 7w REG 253,0 4294967296 ... /var/log/nginx/access.log (失联)。
这里统计出来的4GiB空间根本不会出现在 ls /var/log/nginx 的结果里,因为对应的目录项已经被删掉了;但nginx的1842号进程还把它当成合法的写入目标。别直接对着文件描述符做删除操作,也不要上来就直接杀PID看效果。先确认这个进程归属于哪个服务管理器单元、当前有没有业务流量,还有日志轮转配置是不是已经把新日志指向了正确的存储路径。
把 PID 还原成对应的服务和启动方式
依次查看 ps -fp 1842、sudo readlink -f /proc/1842/exe、sudo service status nginx --no-pager 和 sudo ls -l /proc/1842/fd/7。如果是业务自己打包的守护进程,进程名大概率不会和文件名一致;这种情况就顺着父进程、启动参数和部署脚本往回溯源就行。
从失联句柄回到可控的恢复动作
恢复动作按照影响面从小到大排序。对支持重新打开日志文件的nginx、HAProxy或者自研服务,优先用官方指定的信号或者管理接口操作;对服务管理器托管、可以快速拉起的无状态服务,再考虑受控重启。每一步操作前先把PID、服务状态和当前磁盘的使用率数据留存下来,操作完立刻复查状态。
比如先执行 sudo service reload nginx,等两秒之后再执行 sudo lsof -nP -p 1842 | grep 失联 || true 和 df -hT /var 核验状态。如果失联条目还在,就说明reload操作没有关闭旧的日志句柄,或者reload之后worker进程的PID已经全部更新。这时候去翻对应服务的官方文档或者部署脚本,确认正确的reopen操作方式;生产环境里重启前,要提前确认健康检查、连接摘除和回滚窗口都准备妥当。
- 操作前记录PID、服务状态和
df -hT。 - 优先执行reload或者reopen操作,确认新日志文件已经在正常写入增长。
- 操作后再次执行
lsof +L1核验,不能只等监控告警消失就完事。 - 如果磁盘使用率没有下降,检查是不是还有其他PID持有对应的失联文件句柄。
服务管理器 journal 为什么清理后仍有空间占用
如果大空间占用的来源是 /var/log/journal,别直接套普通文本日志的轮转清理经验。journalctl --disk-usage 统计的时候会把活跃journal文件也算进去,而 --vacuum-size 只处理归档状态的journal文件,所以执行完清理之后,已用空间大概率不会直接降到你预期的数值。
可以先执行 sudo journalctl --disk-usage,再依次执行 sudo journalctl --rotate、sudo journalctl --vacuum-time=14days,最后重新查看磁盘使用情况。如果团队要求按固定容量控制journal大小,也可以配置 --vacuum-size=2G;操作前先确认日志保留周期、审计要求和故障回溯窗口符合内部规范。
碰到journal空间持续异常增长的问题,要去检查 /etc/服务管理器/journald.conf 里的 日志容量上限、运行日志容量上限 等相关配置,修改完之后用 service restart 服务管理器-journald 或者对应发行版文档指定的方式重新加载配置。

常见问题:误区与边界状态
为什么 rm 删完文件,df 统计的使用率完全没变?
文件已经从文件夹里删掉之后,你再执行多少次rm都没有新的可操作目标。空间真正被回收,要等最后一个打开这个文件的文件描述符被关闭,一般对应服务执行reload、主动reopen日志或者受控重启的动作。
lsof +L1 没有输出,差值还可能来自哪里?
继续排查挂载点遮挡、容器存储层、文件系统快照、系统预留块,还有不同用户权限导致的文件可见性差异。也可以对比 findmnt -T /var 和 du -x 的统计覆盖范围,找出漏算的部分。
journalctl --vacuum-size 为什么没清到指定的大小?
这个命令只会处理符合条件的归档journal文件,当前正在写入的active文件还是会被 --disk-usage 统计进已用空间。先手动执行一次轮转再跑vacuum操作,最终的统计结果就完全符合预期了。
能不能直接重启持有失联文件的进程?
可以当成最后的兜底恢复手段,但操作前必须先确认服务可用性、现有连接的处理逻辑、健康检查规则和回滚路径。无状态服务和有状态服务不能直接用同一套重启流程。
把排查动作做成值班习惯
这类告警最容易踩的坑就是「看起来清理成功了,但是根因完全没解决」。把 df -hT、目录级 du -x、lsof +L1 和服务状态校验放进同一份值班检查单,操作完成后要核验新日志正常写入、失联句柄完全清零、文件系统使用率回落这三个状态。日志轮转本身只是切换了日志文件的名字,真正释放磁盘空间的节点,永远取决于最后一个持有句柄的进程什么时候关闭文件。
Go regexp 编译放请求路径为什么拖慢 p99:预编译、缓存和基线对比
- 上一篇
- Go regexp 编译放请求路径为什么拖慢 p99:预编译、缓存和基线对比
- 下一篇
- Docker Desktop 怎么清理无用镜像:从磁盘告警到空间回收
-
- 文章 · linux | 6小时前 | [] · []
- Linux 文件句柄突然耗尽怎么查:从 /proc/PID/fd 找到泄漏进程并安全恢复
- 386浏览 收藏
-
- 文章 · linux | 2天前 | Linux · 服务管理 · 安全加固 · 服务部署 · 文件权限 · Linux 迁移 服务单元 DynamicUser StateDirectory 服务降权 持久目录
- Linux DynamicUser 配合 StateDirectory:服务降权后的持久目录怎么迁移
- 462浏览 收藏
-
- 文章 · linux | 2天前 | Linux · 故障排查 · 服务管理 · 进程生命周期 · Linux 服务状态 active exited Type=oneshot RemainAfterExit 常驻进程
- Linux 服务显示 active (exited) 却没有常驻进程:一次性任务与常驻 worker 怎么区分
- 331浏览 收藏
-
- 文章 · linux | 3天前 | [] · []
- Linux 服务明明启动成功,环境变量为什么没生效:从 EnvironmentFile 到 daemon-reload 的排查
- 450浏览 收藏
-
- 文章 · linux | 2星期前 |
- Linux 磁盘空间没满但仍写不进去:inode 用尽的定位、清理与复测
- 317浏览 收藏
-
- 文章 · linux | 2星期前 | [] · []
- Linux inotify 监听数量不够怎么查:max_user_watches、进程占用与持久化配置
- 382浏览 收藏
-
- 文章 · linux | 2星期前 |
- Ubuntu 22.04 升级 24.04 后 Linux 服务环境变量失效:旧 unit 的迁移与回滚
- 429浏览 收藏
-
- 文章 · linux | 2星期前 |
- Linux journalctl 重启后日志不见怎么办:--list-boots、持久化目录与核对方法
- 292浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ljg-skills
- ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
- 4807次使用
-
- MELO音乐
- MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
- 4399次使用
-
- UniScribe
- UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
- 4347次使用
-
- 剧云
- 剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
- 4581次使用
-
- 万象有声
- 万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
- 4530次使用
-
- golang xorm 自定义日志记录器之使用zap实现日志输出、切割日志(最新)
- 2023-02-24 432浏览
-
- Go语言常用的打log方式详解
- 2023-02-24 485浏览
-
- Go常用技能日志log包创建使用示例
- 2023-01-28 105浏览
-
- Go学习笔记之Zap日志的使用
- 2023-01-19 360浏览
-
- Go实现整合Logrus实现日志打印
- 2023-01-07 229浏览

