journald 日志管理实战:持久化、限额与 journalctl 查询手册

在一台出过故障的服务器上,第一件事往往是看日志,而最让人无奈的情况是:重启之后 journald 日志全没了,只剩内存里那点缓冲;或者反过来,日志把系统盘吃满导致其他服务写不进数据。本文把 systemd-journald 的持久化、限额和查询一次讲透,让日志既不丢、也不失控。

适用环境:Rocky Linux 9 / RHEL 9(systemd 252),Ubuntu 22.04 做法基本一致。文中主机名、IP 均为占位示例。

先理清 journald 与 rsyslog 的关系

journald 是 systemd 的日志收集组件,接收来自内核、服务标准输出与 /dev/log 的日志,以结构化二进制格式保存,并提供 journalctl 查询。每条记录带单元名、优先级、启动周期等元数据。

rsyslog 则是传统的文本日志守护进程,负责把日志落成 /var/log/messages、/var/log/secure 这类文本文件,并可按规则转发到远程日志服务器。两者不是替代关系:现代发行版默认 journald 在前、rsyslog 在后,前者通过 ForwardToSyslog 把日志再喂给后者。需要文本日志、远程转发、与老监控系统对接时保留 rsyslog;只需本机排障时,仅 journald 也够用。

前置条件

  • sudo 权限账号;
  • 系统使用 systemd 作为 init(RHEL 系与 Ubuntu 默认均是);
  • 了解本机日志保留需求:留多少天、系统盘能给日志多少空间。

开启持久化存储

journald 默认 Storage=auto:当 /var/log/journal 目录存在时才持久化,否则只写 /run/log/journal(内存),重启即丢。Rocky Linux 9 上该目录默认不存在,需要手动创建;同理,部分精简镜像也会缺这个目录。

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

重启后确认模式已经切换:

journalctl --disk-usage
ls /var/log/journal/*/

能看到 system.journal 文件落在 /var/log/journal 下即为持久化生效。也可以把 Storage 改成 persistent(缺目录时自动创建),但运维上更建议显式建目录并改配置,让意图可审计。若 /var/log 是单独分区且开机早期不可用,journald 会先写内存再合并,属正常现象。

设置限额参数

限额写在 /etc/systemd/journald.conf(或 /etc/systemd/journald.conf.d/ 下的片段文件,后者更利于配置管理)。注释掉的默认值可以直接在主文件里改,也可新建片段:

[Journal]
Storage=persistent
SystemMaxUse=2G
SystemKeepFree=5G
SystemMaxFileSize=128M
MaxRetentionSec=30day
ForwardToSyslog=yes

几个参数的口径要说清:

  • SystemMaxUse:journal 文件在磁盘上最多占用的总空间,超限后删最旧的归档文件。未设时默认取文件系统容量的 10%,上限 4G。
  • SystemKeepFree:磁盘上至少要保留的空闲空间,journald 会在「占用上限」和「保留空闲」两个约束中取更严的那个。系统盘较小时这个参数比 MaxUse 更早触发清理。
  • SystemMaxFileSize:单个 journal 文件的最大体积,决定轮转粒度,太小会产生大量碎片文件,一般 64M–128M 即可。
  • MaxRetentionSec:按时间保留的最长时长,与空间限额是「或」的关系,谁先到都触发删除。注意它只管归档文件的删除时机,正在写入的活动文件不会被强删。
  • RateLimitIntervalSec / RateLimitBurst:单服务日志限速,默认 30 秒内 10000 条。日志洪泛时超出部分会被丢弃并留 suppressed 提示,发现「日志断片」先查这里。

改完配置重启 journald 生效。临时清理存量日志用 vacuum 系列命令,按空间或时间删除归档文件:

sudo journalctl --vacuum-size=500M
sudo journalctl --vacuum-time=7d
sudo journalctl --rotate && sudo journalctl --vacuum-time=1s

最后一条组合先轮转归档再清理,紧急腾空间时可用,生产环境慎用。

journalctl 常用查询组合

按单元、进程与优先级过滤

排障最常用的是限定服务单元,再叠加时间与优先级。优先级沿用 syslog 的 0(emerg)到 7(debug),-p err 表示只看 err 及更严重级别。

journalctl -u nginx.service --since "2026-11-08 09:00" --until "2026-11-08 10:00"
journalctl -u app.service -p err --since today
journalctl _PID=1234 --since "-30 min"
journalctl -u app.service -n 200 --no-pager

--no-pager 适合在脚本里取日志,避免被 less 卡住;交互查看时默认分页即可。输出格式可用 -o json 或 -o verbose 拿到完整字段,写日志采集脚本时很实用。

按启动周期回看

「重启之后问题消失,只想看上一次启动发生了什么」是 journald 相对文本日志的最大优势,前提是持久化已开启:

journalctl --list-boots
journalctl -b -1 -p warning
journalctl -b -1 -u app.service -e

-b 0 是本次启动,-b -1 是上一次。-e 跳到日志末尾,配合 -f(实时跟踪,类似 tail -f)是盯发布的常用姿势。另有 -x 可给部分条目附加解释性说明,对不熟悉的报错能省一轮搜索,适合初筛时用。

看内核与磁盘占用

journalctl -k -b 0 --since "-1 hour"
journalctl --disk-usage
journalctl --verify

-k 只看内核消息(等价于 dmesg 的持久化版本)。--verify 校验 journal 文件完整性,怀疑日志文件损坏时先跑它。

是否转发到 rsyslog

保留 rsyslog 的理由主要有三:合规或审计要求文本格式的 /var/log/secure 等文件;日志要集中转发到日志平台,用 rsyslog 的队列与重试更成熟;老脚本和监控项直接 grep 文本文件。如果都不沾边,可关掉转发(ForwardToSyslog=no)并停用 rsyslog,少一份磁盘写入。

需要注意 Rocky Linux 9 上 rsyslog 默认读取 journal 时走 imjournal 模块,与 ForwardToSyslog 是两条路径,按发行版的默认配置来即可,不要同时开两种采集造成重复日志。Ubuntu 22.04 默认同样装有 rsyslog,处理方式一致。

验证

  • journalctl --disk-usage 能看到归档日志占用且数值随重启增长,说明持久化生效;
  • 重启一次机器后 journalctl --list-boots 能列出至少两个启动周期;
  • journalctl -u systemd-journald --since "-5 min" 无报错,配置语法无误;
  • 人为写入一条测试日志 logger -p user.err "journald test",能立即用 journalctl -p err --since "-1 min" 查到。

常见问题

重启后日志丢失。十有八九是没开持久化:检查 /var/log/journal 是否存在、Storage 取值;另外确认 /var/log 不是 tmpfs 或被某个清理脚本定期清空。

日志把磁盘占满。先 journalctl --disk-usage 确认是不是 journald 的锅,再检查限额是否被片段配置覆盖(systemd-analyze cat-config systemd/journald.conf 可看合并结果)。注意 SystemKeepFree 是以当时空闲空间计算的,盘本身快满时它救不了场,先 vacuum 应急再谈保留策略。

journalctl 查询很慢。多半是日志文件过多过大、且查询没带过滤条件。查询时尽量带 -u、-b 和时间范围;归档文件碎片化严重时,可适当调大 SystemMaxFileSize 减少文件数。

某服务日志不全、有 suppressed 字样。这是触发了限速,被丢弃的条数会写在提示里。临时调高该服务的 LogRateLimitBurst(单元级)或全局限速,同时推动业务方降噪,单纯调大限额只是把问题推迟。

小结

journald 上线只需三步:建目录开持久化、按盘大小与保留天数设好限额、记住 -u/-b/-p/--since 这组查询参数。剩下的取舍只有一件:要不要把日志继续交给 rsyslog 做文本落地与集中转发。分工明确,日志就既不丢、也不失控了。

发表回复

后才能评论