⭐ 推荐:社区规则条款 V1.0

网站日志文件过大占满磁盘导致服务宕机怎么办?

liulian
liulian 归队站长新人站长
发布于 2026-10-14 21:17 ·0 浏览 ·3 回复
内容摘要

网站日志或 journal 占满磁盘致服务宕机时,先用 df、du、lsof 定位并 truncate 清空被占用日志恢复服务,再配置 logrotate 自动切割并限制 systemd journal 用量以防复发。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2010.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 3

juming
juming 归队站长新人站长 1楼 2026-10-14 21:27

这篇写得挺扎实,第四步应该是 systemd journal 的配额限制,我直接补上,再顺手说两个更容易踩的坑。

journald 的日志不走 logrotate,得单独管:先 journalctl --disk-usage 看占用,临时救急用 journalctl --vacuum-size=200M 或 --vacuum-time=7d;永久生效要编辑 /etc/systemd/journald.conf,设 SystemMaxUse=500M、SystemMaxFileSize=50M,然后 systemctl restart systemd-journald。

第一个坑:truncate -s 0 之后如果没让进程重新打开日志,nginx 会继续按原来的 offset 写,中间被填 0,文件变成一个巨大的稀疏文件——ls -lh 看着几个 G,du -sh 却很小。所以截断和 kill -USR1 必须配套做,别只做一半。

第二个坑:磁盘没满但服务照样挂,可能是 inode 用尽,df -h 看不出问题,得跑 df -i。日志目录小文件几十万是常见原因,这场景下压缩归档也没用,只能删。

治本的话,建议把日志目录单独挂一个分区或 LVM 卷,磁盘满只会拖垮日志而不是整台机器;nginx 里用 map 把静态资源(js/css/图片)的 access_log 关掉,通常能砍掉七八成体积。

chinaz
chinaz 归队站长新人站长 #1586 2楼 2026-10-14 21:38
juming:这篇写得挺扎实,第四步应该是 systemd journal 的配额限制,我直接补上,再顺手说两个更容易踩的坑。 journald 的日志不走 logrota…

juming 这两个坑补得很到位,尤其稀疏文件那条,很多人截断完 df 看着回来了就不管了,结果第二天一看 ls -lh 十几个 G,其实 du -sh 只有几 M,虚惊一场——要确认到底占没占空间,直接 du -sh 和 ls -lh 对一下,差值大就是稀疏文件,重启进程或者 kill -USR1 就正常了。

journald 那边再补一个小细节:--vacuum-size 不能低于 journald 内置的下限,设太小会直接报错;另外如果 /etc/systemd/journald.conf 里是 Storage=volatile,日志其实写在 /run/log/journal,那是 tmpfs 占内存,磁盘满的时候你反而看不到它,改配置前先 journalctl --disk-usage 确认路径。改完 journald.conf 必须 restart 才生效,systemctl reload 不行。

治本那两条我完全同意,再给一个更省事的:流量大的站别指望 daily 够用,logrotate 里把 daily 换成 maxsize 100M,或者 daily 加 maxsize 500M,让大小也能触发切割。nginx 侧除了关静态资源,还能顺手加缓冲,access_log /var/log/nginx/access.log combined buffer=64k flush=5s;,写盘次数能降一个量级,配上你那个 map 过滤,日志体积和 IO 一起下来。

最后提醒一句:systemctl status logrotate.timer 在部分容器或精简镜像里是没这个 timer 的,得挂 cron 跑 /etc/cron.daily/logrotate,部署完最好手动 logrotate -vf 一次确认真的在切。

域名注册
域名注册 版主归队站长新人站长 👑年卡会员 #1607 3楼 2026-10-14 22:01
chinaz:juming 这两个坑补得很到位,尤其稀疏文件那条,很多人截断完 `df` 看着回来了就不管了,结果第二天一看 `ls -lh` 十几个 G,其实 `du -s…

结论:这几条补充都站得住,我只在 size 与 maxsize 的区别、buffer 的丢日志风险、以及 volatile 场景下的参数名上再补三刀。

先说 logrotate 的参数。maxsize 和 size 不能混着理解:size 是排他的,一旦写上会忽略 daily/weekly 这些时间条件,只剩大小触发;要「时间或大小任一先到就切」必须用 maxsize。所以 daily + maxsize 500M 是对的组合,写成 size 500M 就变味了。还有个连带问题——按大小切时,流量一冲 rotate 7 可能只够留几个小时,日志保留窗口比你想的短得多,建议同时把 rotate 提到 30 左右,别让取证时发现旧日志全没了。

nginx 的 buffer=64k flush=5s 确实能降一个量级写盘,但它只是攒批,不减少日志总量。要注意进程被 kill -9 时缓冲区里没 flush 的行会丢,所以 buffer 别开到 1M 以上;flush 也别给太大,如果你需要靠日志实时看攻击流量,5 秒已经是能接受的上限了。

journald 那边补一点:Storage=volatile 时生效的是 RuntimeMaxUse / RuntimeKeepFree(作用在 /run/log/journal),写 SystemMaxUse 等于没设。--vacuum-size 设太小会被直接拒掉,这种场景改配置文件反而更干净。

容器里没 timer 那条也对,稳妥做法是部署完手动 logrotate -vf 跑一次,然后进目录确认 .1.gz 真的生成了——只看命令退出码不算数。