在使用 systemd-journald 进行日志管理时,遇到内核日志输出过快导致日志丢失的情况时,一般是由于 journald 的缓冲区设置过小,无法处理快速输出的内核消息。本文将介绍问题原因,并给出相应的解决方案。

问题描述

当内核日志输出过快时,systemd-journald 可能会因其内部缓冲区设置过小而无法处理所有日志,导致部分日志信息丢失。表现为系统日志中出现类似以下的错误:

Missed xxx kernel messages

这种情况通常出现在内核大量输出调试信息、系统初始化阶段日志频繁输出,或系统发生较大故障时。

原因分析

systemd-journald 是一个处理系统日志的服务,包括内核日志。它通过监听 /dev/kmsg 获取内核日志信息。journald 使用一个内部缓冲区来暂存日志,如果日志流速过快而 journald 无法及时处理,这个缓冲区会被填满,导致消息溢出或丢失。

默认情况下,journald 的日志缓冲区大小较小,可能无法应对高频率的日志输出。此外,journald 还可能受限于某些系统资源的配置,如最大消息大小、日志文件大小等。

解决方案

我们可以通过以下几个步骤来缓解或解决内核日志丢失问题:

1. 增加 systemd-journald 缓存大小

通过调整 systemd-journald 的配置来增大其缓冲区,可以减少日志丢失的情况。

编辑 journald 的配置文件:

sudo vim /etc/systemd/journald.conf

找到以下参数并进行调整:

# RuntimeMaxUse: 设置运行时日志文件的最大使用空间。
# 可以将此值设为较大的值,例如 100M。
RuntimeMaxUse=100M

# SystemMaxUse: 设置系统日志文件的最大使用空间。
# 可以将此值设为 500M。
SystemMaxUse=500M

# RateLimitInterval: 限制日志接收速率的时间间隔。
# 可以适当延长此时间,例如 10s。
RateLimitInterval=10s

# RateLimitBurst: 限制日志接收速率的最大突发数。
# 增加突发限制,比如 10000。
RateLimitBurst=10000

保存并关闭文件,然后重启 journald 服务使配置生效:

sudo systemctl restart systemd-journald

2. 调整内核日志环形缓冲区的大小

内核日志存储在一个环形缓冲区中,该缓冲区的大小可以通过 dmesg 命令查看和调整。默认的缓冲区可能较小,可以通过 kernel 命令行参数 log_buf_len 来调整。

编辑 grub 配置文件:

sudo vim /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT 行中添加如下参数:

GRUB_CMDLINE_LINUX_DEFAULT="log_buf_len=16M"

这将内核日志缓冲区设置为 16M。保存并更新 grub:

sudo update-grub

然后重启系统以应用更改:

sudo reboot

3. 禁用日志速率限制

如果日志速率限制不符合当前系统需求,可以考虑禁用速率限制,尤其是在开发和调试环境中:

sudo vim /etc/systemd/journald.conf

在配置文件中禁用日志速率限制:

RateLimitInterval=0
RateLimitBurst=0

保存文件并重启 systemd-journald 服务:

sudo systemctl restart systemd-journald