登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux systemd-journald 持久化日志的配置方法

来源:17golang原创

时间:2026-10-17 08:15:06 180浏览 收藏

我排查 Linux 服务重启后的问题时,最怕看到的不是报错,而是“昨天的日志已经不在了”。很多机器上的 systemd-journald 并没有坏,只是日志还停留在运行时目录,重启后自然无法继续追溯。要让日志跨重启保留,关键是把存储模式、目录位置和轮转边界一起设计。

本文只讨论三件事:怎样启用持久化目录,怎样确认运行时日志已经刷新到磁盘,以及怎样用空间和时间参数控制 journal 文件增长。示例配置是可改造的生产骨架,不代表已经在某台机器上执行过。

官方参考地址:https://www.freedesktop.org/software/systemd/man/latest/journald.conf.html

先把 /run 和 /var 的日志职责分开

systemd-journald 的 Storage= 决定日志保存在哪里。volatile 只使用内存中的 /run/log/journal;persistent 优先写入磁盘上的 /var/log/journal,在早期启动或磁盘不可写时才回退到运行时目录;auto 则根据 /var/log/journal 是否存在来选择持久化或易失模式。

这也是“配置明明是 auto,为什么仍然没有历史日志”的常见原因:目录不存在时,auto 的行为更接近 volatile。如果你明确要求跨重启保存,使用 Storage=persistent 更容易读懂,也不依赖目录是否被提前创建。

systemd-journald 从运行时目录到持久化目录的存储边界静态说明图
图1:systemd-journald 存储目录与刷新组件的结构说明图,不是终端或运行截图。

用 drop-in 配置持久化存储

官方文档建议使用 *.conf.d drop-in 覆盖本地配置。这样不会直接改动发行版提供的主配置文件,后续查看时也能立刻知道哪些参数是本机的运维决定。

# 创建本地 drop-in 目录,避免直接改发行版主配置文件
sudo install -d -m 0755 /etc/systemd/journald.conf.d

# 写入持久化存储配置;文件名靠后的片段通常拥有更高的覆盖优先级
sudo tee /etc/systemd/journald.conf.d/60-persistent.conf > /dev/null 

这里的关键不是“重启一次服务”本身,而是让配置读取、目录可写和日志刷新形成闭环。journalctl --flush 会请求 journald 把 /run/log/journal 中暂存的数据移到 /var/log/journal;如果持久化存储没有生效,它不会凭空创建一个可用的磁盘日志链路。

目录创建与启动早期日志要怎么处理

如果系统采用 Storage=auto,创建 /var/log/journal 本身就会改变存储选择;如果已经明确写了 Storage=persistent,目录仍然要保证存在且可写。常见的做法是交给 systemd 的临时文件规则创建目录:

# 按 systemd 的目录与权限规则创建持久化 journal 目录
sudo systemd-tmpfiles --create --prefix=/var/log/journal

# 重新加载并刷新,覆盖“配置已改但旧日志还在 /run”这类场景
sudo systemctl restart systemd-journald
sudo journalctl --flush

# 查看 journal 文件当前占用;该命令只读,不会主动删除日志
sudo journalctl --disk-usage

启动早期的日志可能先写到 /run/log/journal,等磁盘和目标目录可用后再转移。官方文档把这个动作交给 systemd-journal-flush.service,手动执行 --flush 适合配置变更后的明确收尾。不要把“能看到当前日志”误判为“日志已经跨重启持久化”。

轮转边界:空间限制和时间限制是两套规则

持久化之后,新的问题通常是磁盘会不会被日志慢慢吃满。SystemMaxUse= 限制持久化 journal 总体最多占用多少空间,SystemKeepFree= 要求为其他数据保留多少空闲空间,journald 会采用两者中更严格的限制。SystemMaxFileSize= 控制单个 journal 文件的上限,影响轮转粒度;SystemMaxFiles= 控制保留的文件数量。

如果团队有明确的留存期限,再考虑 MaxRetentionSec=。它按时间删除过旧的 journal 文件;不要只写一个很小的 SystemMaxUse 就假设一定能保留固定天数,因为实际天数还取决于日志写入量。

systemd-journald 空间限制、文件轮转与时间保留的静态关系说明图
图2:journal 文件、空间边界和时间保留之间的关系说明图,不是监控结果截图。
[Journal]
# 持久化日志最多使用 2G,同时尽量给系统保留 4G 空间
Storage=persistent
SystemMaxUse=2G
SystemKeepFree=4G

# 控制单文件大小与文件数量,让空间回收更有粒度
SystemMaxFileSize=128M
SystemMaxFiles=12

# 有明确合规留存要求时再启用时间上限;单位支持 day、week 等
MaxRetentionSec=30day

这些设置会影响 journald 的持续维护,但不会把正在写入的活动文件当成普通旧文件立即删除。尤其是手动清理时,--vacuum-size、--vacuum-time 和 --vacuum-files 只针对归档文件;当前活动文件仍可能让 --disk-usage 看起来高于目标值。

手动清理时先轮转,再 vacuum

遇到磁盘告警,我更倾向于先把当前文件轮转,再执行一次受控清理,这样本次已经写入的内容也有机会进入归档集合。下面的命令是维护动作,不应替代长期配置:

# 先把当前活动文件标记为归档,再按时间和空间清理旧归档
sudo journalctl --rotate --vacuum-time=30d --vacuum-size=2G

# 只查看剩余 journal 占用;不访问线上页面,也不修改服务配置
sudo journalctl --disk-usage

--vacuum-time 适合按时间清理,--vacuum-size 适合给磁盘设置硬边界;两者可以一起用,最终会同时受限。生产环境里应先根据故障追溯需求决定留存时间,再用空间上限兜底,而不是看到磁盘紧张就无限制地删除。

最后用一张表复查配置边界

目标主要配置或命令容易误解的地方
跨重启保存Storage=persistent、/var/log/journalauto 依赖持久化目录是否存在
接住启动早期日志/run/log/journal、journalctl --flush暂存目录不等于最终持久化目录
限制磁盘占用SystemMaxUse、SystemKeepFree空间回收不会让活动文件立刻消失
控制轮转粒度SystemMaxFileSize、SystemMaxFiles文件数量限制主要作用于归档文件
一次性清理--rotate + --vacuum-time/size这是维护动作,不替代长期配置

相关问题

只设置 Storage=persistent 就够了吗?

还要确认 /var/log/journal 可写,并在配置变更后执行刷新。启动早期日志可能先在 /run/log/journal,需要由 flush 动作转移。

为什么 vacuum 后占用没有降到精确值?

vacuum 主要处理归档文件,活动文件仍会计入 --disk-usage;另外空间和文件数量限制只会删除符合条件的旧文件。

SystemMaxUse 和 MaxRetentionSec 应该二选一吗?

不必二选一。时间上限适合表达业务留存要求,空间上限适合保护磁盘,两者一起配置更容易覆盖高写入量场景。

我的经验是,先用 Storage=persistent 解决“重启后没有历史”的根因,再用 SystemMaxUse 和 SystemKeepFree 保护磁盘,最后按故障追溯周期决定是否加入时间留存。这样每个参数都有明确职责,排障时也不容易把目录、刷新和轮转混在一起。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>