日志越攒越多、查起来越费劲?先把 journal 与轮转规则理清楚

举报
yd_228326260 发表于 2026/10/30 14:01:45 2026/10/30
【摘要】 日志越攒越多、查起来越费劲?先把 journal 与轮转规则理清楚磁盘报警常常不是业务数据撑爆的,而是日志。更麻烦的是另一头:真出故障要查的时候,日志要么早被删光了,要么几十个文件翻不到关键那一行。日志治理就两件事:平时别让它无限长,查的时候能按时间、按服务、按级别一下子定位。先分清手里有哪几种日志,再给每一种定规则。 一、先分清:你手里到底有几种日志一台 Linux 服务器上,日志通常分...

日志越攒越多、查起来越费劲?先把 journal 与轮转规则理清楚

磁盘报警常常不是业务数据撑爆的,而是日志。更麻烦的是另一头:真出故障要查的时候,日志要么早被删光了,要么几十个文件翻不到关键那一行。日志治理就两件事:平时别让它无限长,查的时候能按时间、按服务、按级别一下子定位。先分清手里有哪几种日志,再给每一种定规则。

一、先分清:你手里到底有几种日志

一台 Linux 服务器上,日志通常分三路,查法和管法各不相同,混在一起翻最费时间:

# 1. systemd 接管的服务日志:journal
journalctl -u <服务名> --no-pager | tail -n 100
# 2. 传统文本日志:/var/log 下的文件
ls -lh /var/log/
# 3. 应用自己写的文件日志:看应用配置里的 log 路径,别猜
grep -ri "log" /etc/<应用名>/ 2>/dev/null | head -n 20
  • journal 是 systemd 收集的标准输出和标准错误,服务只要走 systemd 启动,日志就进 journal,不用应用自己写文件。
  • /var/log 里的 messages、secure、cron 这类是 rsyslog/syslog 写的文件日志,系统级事件多在这里。
  • 应用自写的文件日志最杂:有的按天切分,有的永远写同一个文件,有的混在数据目录里。先确认它到底写到哪,再谈轮转。

先算一笔账,看看日志到底占了多少,再决定先治哪一路:

# journal 占了多少
journalctl --disk-usage
# /var/log 占了多少,排个序
du -sh /var/log/* 2>/dev/null | sort -rh | head -n 20
df -h /var /var/log 2>/dev/null

如果 /var/log 和根分区是同一个分区,日志长满就是根分区满,服务连写临时文件都写不进去——这就是 10 月 24 日那篇磁盘排查里讲过的连锁反应,日志治理首先是磁盘治理。

二、查日志:先缩范围,再翻内容

日志多的时候,tail 和 grep 全文翻是最慢的路。journalctl 的本事就是先按维度缩圈:

# 只看某个服务、某段时间、某个级别
journalctl -u <服务名> --since "2026-10-30 09:00" --until "2026-10-30 10:00" -p err --no-pager
# 只看上一次启动以来的日志,重启前后的问题用这个分界
journalctl -u <服务名> -b --no-pager | tail -n 200
# 按关键字再缩一圈(journalctl 自带 --grep,不用先管道给 grep 再丢上下文)
journalctl -u <服务名> --since "1 hour ago" --grep "timeout|oom|failed" --no-pager
  • -p 是级别:emerg、alert、crit、err、warning、notice、info、debug。先从 err 起步,确认没漏再放宽到 warning,一上来就看 info 只会被正常日志淹没。
  • --since 支持相对时间(1 hour ago、yesterday)和绝对时间,先定时间窗,再定服务,最后定级别,三个维度一缩,几十万行也能落到几十行。
  • 文本文件日志没有这些维度,就靠 grep + 时间戳:先 grep 出异常行,再按时间前后翻上下文,别只看异常那一行本身。

一个常见误区:查不到就以为没记。先确认两件事:服务是不是走 systemd(不是的话 journal 里本来就没有它),以及日志级别是不是被应用自己调成了只记 error——级别以上的日志没写进来,事后是翻不出来的。

三、journal 的治理:先定上限,再谈清理

journal 默认的存储方式决定了它能活多久。先看当前配置,别直接上手删:

# 当前 journal 的存储与上限
grep -v "^#" /etc/systemd/journald.conf | grep -v "^$"
journalctl --disk-usage

关键的几个配置项,都在 /etc/systemd/journald.conf 里,改完要重启 systemd-journald 才生效:

[Journal]
# persistent 落盘保存,重启后还在;volatile 只放内存,重启就丢;auto 是有 /var/log/journal 目录才落盘
Storage=persistent
# journal 总量上限:超过就按时间从旧到新删,别等磁盘报警才动手
SystemMaxUse=1G
# 单个 journal 文件上限
SystemMaxFileSize=100M
# 给磁盘留的余量:journal 再多也不能把磁盘吃到这个数以下
SystemKeepFree=2G
# 最长保留时间:超过的旧日志自动清理
MaxRetentionSec=30day
  • SystemMaxUse 和 MaxRetentionSec 是两道不同的闸:一个管总量,一个管时间。只设总量不设时间,低频服务的一年前日志可能还占着地方;只设时间不设总量,突发刷屏一天就能把上限顶穿。两个都设,才是“平时不操心”。
  • 手动清理不要直接 rm /var/log/journal/*。journal 的正确清理方式是先轮转、再按量或按时间回收:
# 先把当前正在写的文件封存,再清理,避免删到正在写的文件
journalctl --rotate
# 只保留最近 500M
journalctl --vacuum-size=500M
# 只保留最近 14 天
journalctl --vacuum-time=14d
# 只保留最近 5 个文件
journalctl --vacuum-files=5
  • vacuum 是按时间从旧到新删,删完就找不回来了。动手之前先确认:最近一次故障的时间窗还在保留期内没有;不确定的时候,先把那段时间的日志导出来存档再清:
journalctl -u <服务名> --since "2026-10-29" --until "2026-10-30" > /tmp/<服务名>-2026-10-29.log

四、文本日志的治理:logrotate 不是“删文件”,是“换文件”

应用自写的文件日志靠 logrotate 管。先看它现在是怎么配的,再改:

# 系统全局配置与各应用的独立配置
cat /etc/logrotate.conf
ls /etc/logrotate.d/
cat /etc/logrotate.d/<应用名>

一份常见的应用日志配置,长这样:

/var/log/<应用名>/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    dateext
    maxsize 100M
    sharedscripts
    postrotate
        systemctl reload <服务名> >/dev/null 2>&1 || true
    endscript
}
  • daily + rotate 7:每天切一次,留 7 份;dateext 让切出来的文件名带日期,找某天的日志不用按序号猜。
  • compress + delaycompress:压缩旧日志省空间,但最新切出来的那一份先不压——正在查的日志压成 .gz 还得先解,纯属添乱。
  • maxsize 100M:没到一天、但文件已经 100M 了也先切,别让单个文件长到 grep 都卡。
  • missingok + notifempty:日志文件还没生成、或是空文件的时候别报错,轮转脚本静默跳过。

最关键、也最容易配错的,是切分后怎么让应用写新文件,有两条路,只能选一条:

# 路 A:让应用重新打开日志文件(推荐,前提是应用支持 reload)
postrotate
    systemctl reload <服务名> >/dev/null 2>&1 || true
endscript

# 路 B:应用不支持 reload 时,才用 copytruncate
# 把旧文件内容拷走再截断,原文件句柄不变,应用不用重启也不用 reload
copytruncate
  • 路 A 是正道:reload 后应用打开新文件,旧文件彻底归档。但前提是应用真的支持 reload,不支持的服务 reload 等于没 reload,日志还会继续写旧文件。
  • 路 B 是兜底:copytruncate 在拷贝和截断之间有个极短的窗口,那几行日志可能丢,而且大文件拷贝截断那一下会卡一拍。能用路 A 就别用路 B。
  • 最忌讳的是直接 rm 掉正在写的文件:应用还握着旧文件的句柄,磁盘空间不会释放(这就是 10 月 24 日那篇讲的“删了文件空间没回来”),新日志还继续往那个看不见的旧文件里写,表面上文件没了,磁盘照样满。

五、轮转没生效:先查它到底跑没跑

配好了轮转却没切分,先别怀疑配置,先查轮转本身跑没跑:

# logrotate 是定时任务还是 systemd timer
systemctl status logrotate.timer --no-pager
ls -l /etc/cron.daily/logrotate
# 用调试模式跑一次,看它对某个文件到底会怎么处理,不真正切分
logrotate -d /etc/logrotate.d/<应用名> 2>&1 | head -n 100
# 看上次轮转的状态记录,确认每个文件上次切分是什么时候
cat /var/lib/logrotate/logrotate.status | grep <应用名>
  • logrotate -d 是调试模式,只打印判断过程不真正动手,配错了先在这里看明白,别直接拿生产日志试。
  • 常见的不生效原因就三个:配置文件语法错了(少个 }、路径写错了)、文件权限不对(logrotate 以 root 跑,但 su 指定的用户组不对会直接跳过)、定时任务本身没跑(timer 被停了、cron 服务没起)。
  • 还有一类是“看着没切,其实是条件没到”:daily 是按天算的,rotate 7 的意思是留 7 份,刚配好的第一天本来就不会立刻切出 7 份来。

六、保留多久:按用途定,别一刀切

日志不是留得越久越好,也不是越短越好,按用途分三档就够了:

  • 排障用(系统与应用日志):保留 14 到 30 天。绝大多数故障的复现和定位都在这个窗口里,再久的日志查的概率极低,占的空间却一直在涨。
  • 审计与安全用(登录、sudo、防火墙):保留 90 天或按合规要求。secure、auth.log 这类日志是事后追溯的证据,别跟普通应用日志一个保留期。
  • 业务关键链路:按业务要求单独定,可能是 180 天,也可能要求归档到对象存储而不是留在本机。本机只留近期热数据,冷数据归档出去,别让本机磁盘替归档系统扛着。

定好之后,把规则写进配置而不是记在脑子里:journal 的上限进 journald.conf,文本日志的轮转进 /etc/logrotate.d/,保留期进同一份配置。规则只存在于某次手动清理命令里,下次换人、换机器,立刻就没人知道了。

七、排查清单(收藏版)

  1. 先算账:journalctl --disk-usage 和 du -sh /var/log/*,确认是哪一路在长。
  2. 查日志先缩圈:服务 + 时间窗 + 级别,三维定下来再翻内容。
  3. journal 定上限:SystemMaxUse + MaxRetentionSec 两道闸都设,清理用 journalctl --rotate + --vacuum-*,别直接 rm。
  4. 文本日志走 logrotate:daily + rotate + compress + dateext + maxsize,切分后优先 reload,不支持 reload 才用 copytruncate。
  5. 轮转没生效:先 logrotate -d 调试、再查 timer/cron 和 logrotate.status,别直接拿生产日志试。
  6. 保留期按用途分档:排障 14–30 天,审计按合规,业务冷数据归档出本机。
  7. 清理前先导出故障时间窗的日志存档,删完找不回来,现场没了死因就永远查不出来了。

日志治理的目标不是“磁盘永远不满”,而是“出问题时能立刻找到证据,平时又不用天天盯着它”。上限、轮转、保留期三条规则写进配置里,日志就从一个定时炸弹,变成一个随取随用的工具。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。