<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>日志管理 on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/%E6%97%A5%E5%BF%97%E7%AE%A1%E7%90%86/</link>
        <description>Recent content in 日志管理 on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Thu, 30 Jul 2026 07:00:00 +0800</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/%E6%97%A5%E5%BF%97%E7%AE%A1%E7%90%86/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>磁盘空间为何删了大日志也不释放？一次 df 与 du 相差 60GB 的排查记录</title>
            <link>https://blog.5772447.xyz/posts/76deb068/</link>
            <pubDate>Thu, 30 Jul 2026 07:00:00 +0800</pubDate>
            <guid>https://blog.5772447.xyz/posts/76deb068/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;生产环境一台日志汇聚服务器（CentOS 7.9，数据盘 200GB，挂载在 &lt;code&gt;/data&lt;/code&gt;）负责接收十几个业务模块的应用日志，跑着一个自研的 Java 日志收集进程和 rsyslog。凌晨 4 点半，磁盘使用率告警从 90% 一路蹿到 98%，值班同事按惯例上机清理：找到 &lt;code&gt;/data/applog/&lt;/code&gt; 下一个 62GB 的 &lt;code&gt;collector.log&lt;/code&gt;，直接 &lt;code&gt;rm -f&lt;/code&gt; 删掉，告警却迟迟不恢复。早上 8 点交接班时磁盘仍然显示 98%，新日志开始写入失败，部分业务模块报 &lt;code&gt;No space left on device&lt;/code&gt;，问题升级到我这里。&lt;/p&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;上机第一件事就看磁盘：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ df -h /data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Filesystem      Size  Used Avail Use% Mounted on&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/vdb1       197G  193G  4.2G  98% /data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;但用 &lt;code&gt;du&lt;/code&gt; 统计目录实际占用，怎么算都对不上：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ du -sh /data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;131G    /data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;df&lt;/code&gt; 说用了 193GB，&lt;code&gt;du&lt;/code&gt; 说只有 131GB，凭空差了 60 多GB——恰好接近被删掉的那个大日志的体积。更诡异的是：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;那个 62GB 的 &lt;code&gt;collector.log&lt;/code&gt; 确实已经不在了，&lt;code&gt;ls&lt;/code&gt; 看不到；&lt;/li&gt;&#xA;&lt;li&gt;再删其他小日志文件，&lt;code&gt;df&lt;/code&gt; 的 Used 一点都不降；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;df -i&lt;/code&gt; 看 inode 只用了 3%，排除 inode 耗尽（那是另一类问题，之前写过）；&lt;/li&gt;&#xA;&lt;li&gt;业务持续报写入失败，rsyslog 队列开始堆积。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;删了文件、空间却不还回来，这 60GB 去哪了？&lt;/p&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;第一步确认不是文件系统统计误差&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%80%e6%ad%a5%e7%a1%ae%e8%ae%a4%e4%b8%8d%e6%98%af%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e7%bb%9f%e8%ae%a1%e8%af%af%e5%b7%ae&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第一步：确认不是文件系统统计误差&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;先排除低级可能。&lt;code&gt;df&lt;/code&gt; 统计的是文件系统超级块里的分配信息，&lt;code&gt;du&lt;/code&gt; 是遍历目录树累加文件大小，两者天然会有少量差异（预留块、元数据），但 5% 预留块（ext4 默认）对 197GB 盘也就 10GB 左右，且这台机器早就 &lt;code&gt;tune2fs -m 1&lt;/code&gt; 调到 1% 了。60GB 的差距绝不是统计口径问题。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步想到已删除但仍被打开的文件&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e6%83%b3%e5%88%b0%e5%b7%b2%e5%88%a0%e9%99%a4%e4%bd%86%e4%bb%8d%e8%a2%ab%e6%89%93%e5%bc%80%e7%9a%84%e6%96%87%e4%bb%b6&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二步：想到&amp;quot;已删除但仍被打开&amp;quot;的文件&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;Linux 下 &lt;code&gt;rm&lt;/code&gt; 删除文件，本质是把目录项（dentry）和 inode 的链接数减一。&lt;strong&gt;如果还有进程持有这个文件的文件描述符，inode 的引用计数不为零，内核就不会真正释放数据块&lt;/strong&gt;——文件从目录里消失了，但磁盘空间还被占着。这正是 &lt;code&gt;df&lt;/code&gt;（看块分配）和 &lt;code&gt;du&lt;/code&gt;（看目录树）出现巨大差值的最经典原因。&lt;/p&gt;&#xA;&lt;p&gt;用 &lt;code&gt;lsof&lt;/code&gt; 找被删除但仍被打开的文件：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ lsof +L1 | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$7 &amp;gt; 1073741824&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;COMMAND   PID  USER   FD   TYPE DEVICE   SIZE/OFF NLINK    NODE NAME&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;java    &lt;span style=&#34;color:#ae81ff&#34;&gt;12867&lt;/span&gt; applog  4w   REG  253,16 &lt;span style=&#34;color:#ae81ff&#34;&gt;66571993088&lt;/span&gt;     &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;  &lt;span style=&#34;color:#ae81ff&#34;&gt;524291&lt;/span&gt; /data/applog/collector.log &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;deleted&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;一目了然：PID 12867 的 Java 日志收集进程还拿着 &lt;code&gt;collector.log&lt;/code&gt; 的写句柄（FD 4，&lt;code&gt;w&lt;/code&gt; 表示写模式），&lt;code&gt;NLINK 0&lt;/code&gt; 表示目录项已删，&lt;code&gt;SIZE/OFF&lt;/code&gt; 显示这个&amp;quot;幽灵文件&amp;quot;已经涨到 66GB——&lt;strong&gt;不但没释放，进程还在往里持续写&lt;/strong&gt;，所以删完之后 &lt;code&gt;df&lt;/code&gt; 不降反升。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第三步确认进程为什么攥着句柄不放&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e6%ad%a5%e7%a1%ae%e8%ae%a4%e8%bf%9b%e7%a8%8b%e4%b8%ba%e4%bb%80%e4%b9%88%e6%94%a5%e7%9d%80%e5%8f%a5%e6%9f%84%e4%b8%8d%e6%94%be&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三步：确认进程为什么攥着句柄不放&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;看这个 Java 进程的启动方式和日志配置，发现它用的是自研的文件 Appender，打开日志文件后就再也没有重开逻辑。运维侧曾经给它配过 logrotate，翻 &lt;code&gt;/etc/logrotate.d/collector&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/data/applog/collector.log {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    daily&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rotate 7&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    compress&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    missingok&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;问题就在这：&lt;strong&gt;这份 logrotate 配置既没有 &lt;code&gt;copytruncate&lt;/code&gt;，也没有 &lt;code&gt;postrotate&lt;/code&gt; 里通知进程重开文件&lt;/strong&gt;。logrotate 默认行为是把 &lt;code&gt;collector.log&lt;/code&gt; 改名成 &lt;code&gt;collector.log.1&lt;/code&gt; 再建新文件，但 Java 进程的 FD 还指向改名后的旧 inode，继续往旧文件里写；轮转形同虚设，日志越滚越大。翻历史记录，这个配置是三个月前加的，也就是说这个文件其实已经&amp;quot;假轮转&amp;quot;了三个月，最终膨胀成 62GB 被人工 &lt;code&gt;rm&lt;/code&gt;，又因为句柄未释放变成幽灵占用。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第四步安全释放空间&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e5%9b%9b%e6%ad%a5%e5%ae%89%e5%85%a8%e9%87%8a%e6%94%be%e7%a9%ba%e9%97%b4&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第四步：安全释放空间&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;磁盘只剩 4GB，等不了发版修代码，需要立刻止血。&lt;strong&gt;不能直接 &lt;code&gt;kill -9&lt;/code&gt;&lt;/strong&gt;——日志收集进程内存里还有未落盘的缓冲，粗暴杀掉会丢日志。有两个安全做法：&lt;/p&gt;&#xA;&lt;p&gt;方法一（首选）：通过 &lt;code&gt;/proc&lt;/code&gt; 直接截断这个已删除文件，不用动进程：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 先看看确认目标&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ls -l /proc/12867/fd/4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;l-wx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; applog applog &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; Jul &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt; 08:41 /proc/12867/fd/4 -&amp;gt; /data/applog/collector.log &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;deleted&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 截断为 0，空间立即归还&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ truncate -s &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; /proc/12867/fd/4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;执行完再看 &lt;code&gt;df&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ df -h /data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/vdb1       197G  128G   69G  66% /data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;66GB 空间瞬间回来，业务写入恢复。进程完全无感知，只是它后续写入的偏移量还在 66GB 处——ext4 会把前面的空洞做成稀疏文件，不再占实际块，问题不大，但这个进程终归要在低峰期重启一次，让它重开一个干净的日志文件。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;止血动作汇总：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;lsof +L1&lt;/code&gt; 定位持有已删除文件句柄的进程与 FD；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;truncate -s 0 /proc/&amp;lt;pid&amp;gt;/fd/&amp;lt;fd&amp;gt;&lt;/code&gt; 原地截断，立即归还空间，避免重启进程；&lt;/li&gt;&#xA;&lt;li&gt;当晚低峰重启日志收集进程，消除稀疏文件残留。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;根治动作：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;修正 logrotate 配置，对无重开日志能力的进程加 &lt;code&gt;copytruncate&lt;/code&gt;：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/data/applog/collector.log {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    daily&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    rotate 7&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    compress&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    missingok&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    copytruncate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;推动研发在下个版本给自研 Appender 加上 &lt;code&gt;SIGUSR1&lt;/code&gt; 信号重开日志文件的能力，之后可切回 &lt;code&gt;postrotate&lt;/code&gt; + 信号的标准方案（&lt;code&gt;copytruncate&lt;/code&gt; 在复制窗口内有极小概率丢日志，只是过渡）；&lt;/li&gt;&#xA;&lt;li&gt;给全组同步操作规范：&lt;strong&gt;清理大日志一律先 &lt;code&gt;&amp;gt; file&lt;/code&gt; 截断或走轮转，不要直接 &lt;code&gt;rm&lt;/code&gt; 正在被写入的文件&lt;/strong&gt;。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;三层原因叠加：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;直接原因&lt;/strong&gt;：&lt;code&gt;rm&lt;/code&gt; 删除了仍被进程打开的日志文件，inode 引用未归零，数据块不释放，形成&amp;quot;df 与 du 差 60GB&amp;quot;的幽灵占用；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;深层原因&lt;/strong&gt;：logrotate 配置缺少 &lt;code&gt;copytruncate&lt;/code&gt;/&lt;code&gt;postrotate&lt;/code&gt; 重开机制，对一个不会自己重开日志的进程做了三个月的无效轮转，把单文件养到 62GB；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;流程原因&lt;/strong&gt;：值班清理手册里没有&amp;quot;确认文件是否被进程占用&amp;quot;这一步，直接 &lt;code&gt;rm&lt;/code&gt; 成了肌肉记忆。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控加一层&lt;/strong&gt;：磁盘告警规则里增加 &lt;code&gt;df&lt;/code&gt; 与 &lt;code&gt;du&lt;/code&gt; 差值检查（差值超过 10% 触发提示&amp;quot;存在已删除未释放文件&amp;quot;），并把 &lt;code&gt;lsof +L1&lt;/code&gt; 输出接入巡检脚本；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;轮转配置审计&lt;/strong&gt;：批量检查所有 logrotate 配置，凡目标进程无日志重开能力的，必须有 &lt;code&gt;copytruncate&lt;/code&gt; 或 &lt;code&gt;postrotate&lt;/code&gt; 通知逻辑，纳入配置上线 checklist；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;单文件体积兜底&lt;/strong&gt;：日志目录加单文件大小告警（如超过 5GB 即告警），避免&amp;quot;假轮转&amp;quot;静默养大文件；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;操作规范落地&lt;/strong&gt;：值班手册明确&amp;quot;删大文件前先 &lt;code&gt;lsof&lt;/code&gt; 确认占用；正在写入的文件用 &lt;code&gt;truncate&lt;/code&gt;/&lt;code&gt;&amp;gt;&lt;/code&gt; 截断而非 &lt;code&gt;rm&lt;/code&gt;&amp;quot;。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障本身不复杂，却是 Linux 运维里辨识度最高的经典题：&lt;code&gt;rm&lt;/code&gt; 只删目录项，不删被打开的 inode，&lt;code&gt;df&lt;/code&gt; 和 &lt;code&gt;du&lt;/code&gt; 的差值就是那些&amp;quot;删而未放&amp;quot;的幽灵文件。两条命令就能定位——&lt;code&gt;lsof +L1&lt;/code&gt; 找元凶，&lt;code&gt;truncate -s 0 /proc/&amp;lt;pid&amp;gt;/fd/&amp;lt;fd&amp;gt;&lt;/code&gt; 无损止血，全程不用重启进程。更值得记住的是链路上游：一份没有 &lt;code&gt;copytruncate&lt;/code&gt; 的 logrotate 配置对着不会重开文件的进程空转了三个月，才是把 62GB 巨型日志&amp;quot;养&amp;quot;出来的真正推手。磁盘问题的排查顺序可以固化为：&lt;code&gt;df -h&lt;/code&gt; 看块 → &lt;code&gt;df -i&lt;/code&gt; 看 inode → &lt;code&gt;du&lt;/code&gt; 对账 → 差值大就 &lt;code&gt;lsof +L1&lt;/code&gt;，四步走完，九成磁盘疑难都能落地。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
