当前位置:首页 > 文章列表 > 文章 > linux > Linux 日志轮转后磁盘空间没释放:用 失联文件句柄定位并恢复

Linux 日志轮转后磁盘空间没释放:用 失联文件句柄定位并恢复

来源:17golang原创 2026-08-11 15:07:01 0浏览 收藏

凌晨值班运维最常碰到这种完全不合预期的磁盘告警: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 /vardu -xhd1 /var 2>/dev/null | sort -hdu -xhd1 /var/log 2>/dev/null | sort -h

df 统计的是整个文件系统已经分配出去的磁盘块,du 是遍历目录树统计当前还能直接看到的文件总大小。两者差值很大的时候,除了失联文件之外,还要排查挂载点遮挡、未销毁的容器层,还有文件系统本身预留的空间。要是 /var/log 统计的目录总大小只有18G,而 df 显示已用空间比预期多了30G,接着查未释放的文件句柄,比反复跑清理命令要高效得多。

Linux df 与 du 差额从文件系统占用指向 失联 日志句柄的排查流程

看统计数字时别忽略文件系统类型

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 1842sudo readlink -f /proc/1842/exesudo service status nginx --no-pagersudo ls -l /proc/1842/fd/7。如果是业务自己打包的守护进程,进程名大概率不会和文件名一致;这种情况就顺着父进程、启动参数和部署脚本往回溯源就行。

从失联句柄回到可控的恢复动作

恢复动作按照影响面从小到大排序。对支持重新打开日志文件的nginx、HAProxy或者自研服务,优先用官方指定的信号或者管理接口操作;对服务管理器托管、可以快速拉起的无状态服务,再考虑受控重启。每一步操作前先把PID、服务状态和当前磁盘的使用率数据留存下来,操作完立刻复查状态。

比如先执行 sudo service reload nginx,等两秒之后再执行 sudo lsof -nP -p 1842 | grep 失联 || truedf -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 --rotatesudo journalctl --vacuum-time=14days,最后重新查看磁盘使用情况。如果团队要求按固定容量控制journal大小,也可以配置 --vacuum-size=2G;操作前先确认日志保留周期、审计要求和故障回溯窗口符合内部规范。

碰到journal空间持续异常增长的问题,要去检查 /etc/服务管理器/journald.conf 里的 日志容量上限运行日志容量上限 等相关配置,修改完之后用 service restart 服务管理器-journald 或者对应发行版文档指定的方式重新加载配置。

Linux 从 失联 日志句柄确认进程后通过 reload 或 journal rotate 恢复磁盘空间

常见问题:误区与边界状态

为什么 rm 删完文件,df 统计的使用率完全没变?

文件已经从文件夹里删掉之后,你再执行多少次rm都没有新的可操作目标。空间真正被回收,要等最后一个打开这个文件的文件描述符被关闭,一般对应服务执行reload、主动reopen日志或者受控重启的动作。

lsof +L1 没有输出,差值还可能来自哪里?

继续排查挂载点遮挡、容器存储层、文件系统快照、系统预留块,还有不同用户权限导致的文件可见性差异。也可以对比 findmnt -T /vardu -x 的统计覆盖范围,找出漏算的部分。

journalctl --vacuum-size 为什么没清到指定的大小?

这个命令只会处理符合条件的归档journal文件,当前正在写入的active文件还是会被 --disk-usage 统计进已用空间。先手动执行一次轮转再跑vacuum操作,最终的统计结果就完全符合预期了。

能不能直接重启持有失联文件的进程?

可以当成最后的兜底恢复手段,但操作前必须先确认服务可用性、现有连接的处理逻辑、健康检查规则和回滚路径。无状态服务和有状态服务不能直接用同一套重启流程。

把排查动作做成值班习惯

这类告警最容易踩的坑就是「看起来清理成功了,但是根因完全没解决」。把 df -hT、目录级 du -xlsof +L1 和服务状态校验放进同一份值班检查单,操作完成后要核验新日志正常写入、失联句柄完全清零、文件系统使用率回落这三个状态。日志轮转本身只是切换了日志文件的名字,真正释放磁盘空间的节点,永远取决于最后一个持有句柄的进程什么时候关闭文件。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go regexp 编译放请求路径为什么拖慢 p99:预编译、缓存和基线对比Go regexp 编译放请求路径为什么拖慢 p99:预编译、缓存和基线对比
上一篇
Go regexp 编译放请求路径为什么拖慢 p99:预编译、缓存和基线对比
Docker Desktop 怎么清理无用镜像:从磁盘告警到空间回收
下一篇
Docker Desktop 怎么清理无用镜像:从磁盘告警到空间回收
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    4807次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    4399次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    4347次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    4581次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    4530次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码