Linux 系统 systemd-journald 日志管理故障排查实战

一、概述

systemd-journald 是 systemd 系统和服务管理器的日志守护进程,负责收集和管理系统日志。它取代了传统的 syslog 方案,提供了结构化日志、高效存储和强大的查询能力。

1.1 核心特性

  • 结构化日志:支持键值对格式,便于查询和过滤
  • 元数据丰富:自动记录进程 ID、用户 ID、可执行文件路径等
  • 高效存储:使用二进制格式,支持压缩和索引
  • 多源采集:收集内核日志、系统服务日志、标准输出/错误等

1.2 日志来源

来源类型 说明 示例
Kernel 内核消息 dmesg
Syslog 传统 syslog 消息 /dev/log
Stdout/Stderr 服务标准输出 journalctl -t nginx
Audit 审计日志 auditd
Custom 自定义日志 systemd-cat

二、架构与配置

2.1 组件架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌─────────────────────────────────────────────────────────┐
│ 应用程序/服务 │
└─────────────────────────┬───────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│ systemd-journald (日志守护进程) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 日志采集 │ │ 日志存储 │ │ 日志查询 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────┬───────────────────────────────┘

┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 持久化 │ │ 轮转 │ │ 转发 │
│ 存储 │ │ 清理 │ │ syslog │
└──────────┘ └──────────┘ └──────────┘

2.2 配置文件

主配置文件:/etc/systemd/journald.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[Journal]
# 存储模式:persistent=持久化,volatile=仅内存,auto=自动
Storage=persistent

# 日志目录(仅 persistent 模式有效)
# RuntimeDirectory=/run/log/journal
# SystemDirectory=/var/log/journal

# 最大磁盘使用量
SystemMaxUse=4G
SystemKeepFree=1G
SystemMaxFileSize=500M

# 运行时最大使用量(volatile 模式)
RuntimeMaxUse=100M
RuntimeKeepFree=50M

# 保留时间
MaxRetentionSec=1month

# 转发到 syslog
ForwardToSyslog=yes

# 转发到控制台
ForwardToConsole=no

# 转发到内核
ForwardToKmsg=no

# 压缩级别(lz4, xz, zstd)
Compress=yes

# 速率限制
RateLimitIntervalSec=30s
RateLimitBurst=10000

2.3 配置生效

1
2
3
4
5
6
# 修改配置后重启服务
sudo systemctl restart systemd-journald

# 验证配置
journalctl --disk-usage
systemctl status systemd-journald

三、常用命令与查询

3.1 基础查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看所有日志
journalctl

# 查看最近 100 行
journalctl -n 100

# 实时跟踪日志
journalctl -f

# 查看本次启动后的日志
journalctl -b

# 查看指定启动的日志
journalctl -b -1 # 上次启动
journalctl -b -2 # 上上次启动

# 列出所有启动记录
journalctl --list-boots

3.2 时间过滤

1
2
3
4
5
6
7
8
9
10
# 指定时间范围
journalctl --since "2026-03-20 10:00:00" --until "2026-03-20 12:00:00"

# 相对时间
journalctl --since "1 hour ago"
journalctl --since "30 min ago"

# 今天/昨天
journalctl --since today
journalctl --since yesterday

3.3 服务过滤

1
2
3
4
5
6
7
8
9
10
# 指定服务
journalctl -u nginx
journalctl -u sshd
journalctl -u docker

# 多个服务
journalctl -u nginx -u php-fpm

# 用户服务
journalctl --user -u myapp

3.4 优先级过滤

1
2
3
4
5
6
7
8
9
10
11
# 错误及以上级别
journalctl -p err

# 警告及以上
journalctl -p warning

# 仅紧急
journalctl -p emerg

# 优先级级别
# 0 emerg | 1 alert | 2 crit | 3 err | 4 warning | 5 notice | 6 info | 7 debug

3.5 输出格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 详细格式(默认)
journalctl -o verbose

# JSON 格式
journalctl -o json

# JSON 流格式(每行一个 JSON)
journalctl -o json-pretty

# 简短格式
journalctl -o short

# 原始消息
journalctl -o cat

# 导出格式
journalctl -o export > backup.journal

3.6 高级查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 按字段过滤
journalctl _PID=1234
journalctl _UID=1000
journalctl _COMM=nginx
journalctl _EXE=/usr/sbin/nginx

# 组合查询(AND)
journalctl _SYSTEMD_UNIT=nginx.service _PID=1234

# 正则匹配
journalctl MESSAGE~="error|fail|critical"

# 排除匹配
journalctl MESSAGE!="debug"

四、故障排查

4.1 常见问题分类

问题类型 症状 优先级
日志丢失 查询不到历史日志
磁盘占用高 /var 分区空间不足
服务异常 journald 不启动/崩溃
日志延迟 实时日志更新慢
权限问题 无法访问日志

4.2 故障 1:日志丢失

症状

1
2
3
4
5
6
7
# 查询不到历史日志
journalctl --since "yesterday"
# 输出:No entries

# 启动记录很少
journalctl --list-boots
# 只有最近几次启动记录

排查步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 检查存储模式
cat /etc/systemd/journald.conf | grep -E "^Storage"
# 如果是 volatile,日志只保存在内存中

# 2. 检查日志目录
ls -la /var/log/journal/
# 应该有机器 ID 命名的子目录

# 3. 检查目录权限
ls -la /var/log/ | grep journal
# 应该是 root:systemd-journal 权限

# 4. 检查磁盘使用情况
journalctl --disk-usage
# 查看当前日志占用空间

# 5. 检查配置限制
cat /etc/systemd/journald.conf | grep -E "MaxUse|KeepFree|Retention"

解决方案

1
2
3
4
5
6
7
8
9
10
11
# 方案 1:启用持久化存储
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

# 方案 2:增加保留时间
sudo vim /etc/systemd/journald.conf
# MaxRetentionSec=3month

# 方案 3:增加磁盘配额
# SystemMaxUse=10G

4.3 故障 2:磁盘占用过高

症状

1
2
3
4
5
6
7
# 磁盘空间告警
df -h /var
# /var 使用率超过 90%

# 日志占用过大
journalctl --disk-usage
# Archived and active journals: 15.0G

排查步骤

1
2
3
4
5
6
7
8
9
10
# 1. 查看日志文件分布
ls -lh /var/log/journal/*/
# 查看具体文件大小

# 2. 检查配置限制
grep -E "SystemMaxUse|SystemKeepFree" /etc/systemd/journald.conf

# 3. 查看日志轮转状态
ls -la /var/log/journal/*/*.journal*
# .journal 是活动文件,.journal~ 是归档文件

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 方案 1:手动清理旧日志
sudo journalctl --vacuum-time=7d
# 保留最近 7 天

sudo journalctl --vacuum-size=2G
# 保留最近 2G

sudo journalctl --vacuum-files=10
# 保留最近 10 个文件

# 方案 2:修改配置限制
sudo vim /etc/systemd/journald.conf
# SystemMaxUse=4G
# SystemKeepFree=2G
sudo systemctl restart systemd-journald

# 方案 3:配置 logrotate
sudo vim /etc/logrotate.d/journal
# 添加 logrotate 配置定期清理

4.4 故障 3:journald 服务异常

症状

1
2
3
4
5
6
7
# 服务状态异常
systemctl status systemd-journald
# Active: failed / inactive

# 无法写入日志
logger "test message"
# 无响应或报错

排查步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 检查服务状态
systemctl status systemd-journald
systemctl is-active systemd-journald

# 2. 查看服务日志
journalctl -u systemd-journald -n 50

# 3. 检查依赖服务
systemctl list-dependencies systemd-journald

# 4. 检查 socket 激活
systemctl status systemd-journald.socket

# 5. 检查文件系统
ls -la /run/log/journal/
df -h /run

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 方案 1:重启服务
sudo systemctl restart systemd-journald

# 方案 2:重建 socket
sudo systemctl restart systemd-journald.socket
sudo systemctl restart systemd-journald

# 方案 3:清理损坏的日志文件
sudo systemctl stop systemd-journald
sudo mv /var/log/journal /var/log/journal.bak
sudo systemctl start systemd-journald

# 方案 4:检查 SELinux/AppArmor
getenforce # 如果是 Enforcing,可能需要调整策略

4.5 故障 4:日志延迟或丢失消息

症状

1
2
3
4
5
6
# 日志更新延迟
journalctl -f
# 新产生的日志不实时显示

# 消息丢失
# 应用日志显示已发送,但 journalctl 查不到

排查步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 检查速率限制
journalctl | grep "Rate limiting"
# 查看是否有速率限制触发

# 2. 检查当前限制配置
grep -E "RateLimit" /etc/systemd/journald.conf

# 3. 检查系统负载
top -bn1 | head -20
iostat -x 1 5

# 4. 检查写入队列
cat /proc/sys/kernel/printk

解决方案

1
2
3
4
5
6
7
8
9
10
11
# 方案 1:调整速率限制
sudo vim /etc/systemd/journald.conf
# RateLimitIntervalSec=60s
# RateLimitBurst=20000

# 方案 2:增加系统日志缓冲区
sudo sysctl -w kernel.printk="8 4 1 7"

# 方案 3:检查应用日志方式
# 确保应用使用正确的日志接口
# 对于 systemd 管理的服务,使用 StandardOutput=journal

4.6 故障 5:权限问题

症状

1
2
3
4
5
6
7
# 普通用户无法查看日志
journalctl
# Error: No journal files were found.

# 或权限拒绝
journalctl -u nginx
# Permission denied

排查步骤

1
2
3
4
5
6
7
8
9
10
# 1. 检查用户组
groups $USER
# 应该包含 systemd-journal

# 2. 检查日志目录权限
ls -la /var/log/journal/
# 应该是 0755 或 2755 (setgid)

# 3. 检查文件权限
ls -la /var/log/journal/*/*.journal

解决方案

1
2
3
4
5
6
7
8
9
10
# 方案 1:添加用户到 systemd-journal 组
sudo usermod -aG systemd-journal $USER
# 需要重新登录生效

# 方案 2:修复目录权限
sudo chmod 2755 /var/log/journal
sudo chown root:systemd-journal /var/log/journal

# 方案 3:使用 sudo 查看
sudo journalctl -u nginx

五、日志轮转与归档

5.1 自动轮转机制

systemd-journald 内置轮转机制:

  • 当单个文件达到 SystemMaxFileSize 时轮转
  • 当总大小达到 SystemMaxUse 时清理旧文件
  • 当时间超过 MaxRetentionSec 时清理

5.2 手动轮转

1
2
3
4
5
6
7
8
# 发送轮转信号
sudo kill -USR1 $(cat /run/systemd/journal/pid)

# 或通过 systemd
sudo systemctl kill --kill-who=main --signal=USR1 systemd-journald

# 验证轮转
ls -la /var/log/journal/*/*.journal*

5.3 日志归档

1
2
3
4
5
6
7
8
# 导出日志
sudo journalctl --output=export > /backup/journal-$(date +%Y%m%d).export

# 压缩归档
sudo journalctl --output=export | gzip > /backup/journal-$(date +%Y%m%d).export.gz

# 恢复导入
sudo systemd-journal-restore < /backup/journal.export

5.4 与 logrotate 集成

1
2
3
4
5
6
7
8
9
10
11
12
# /etc/logrotate.d/journal
/var/log/journal/*/*.journal {
weekly
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
systemctl kill --kill-who=main --signal=USR1 systemd-journald
endscript
}

六、与 rsyslog/syslog-ng 集成

6.1 转发到 rsyslog

1
2
3
4
5
6
7
# /etc/systemd/journald.conf
[Journal]
ForwardToSyslog=yes

# /etc/rsyslog.conf
# 确保 imjournal 模块启用
module(load="imjournal")

6.2 从 rsyslog 采集

1
2
3
4
# rsyslog 配置写入 journal
# /etc/rsyslog.d/journal.conf
module(load="omjournal")
*.* :omjournal:

6.3 混合模式最佳实践

1
2
3
应用日志 → journald → rsyslog → 远程日志服务器

本地查询分析

七、性能优化

7.1 写入性能

1
2
3
4
5
6
7
8
9
10
11
# 优化配置
[Journal]
# 使用更快的压缩算法
Compress=lz4

# 增加速率限制
RateLimitIntervalSec=60s
RateLimitBurst=50000

# 调整文件大小
SystemMaxFileSize=1G

7.2 查询性能

1
2
3
4
5
6
7
8
9
# 重建索引
sudo journalctl --relinquish-var
sudo systemctl restart systemd-journald

# 限制查询范围
journalctl --since "1 hour ago" -n 1000

# 使用字段索引
journalctl _SYSTEMD_UNIT=nginx.service

7.3 存储优化

1
2
3
4
5
6
7
8
# 清理无用字段
# 在应用层面减少不必要的日志字段

# 定期清理
sudo journalctl --vacuum-time=14d

# 监控磁盘使用
watch -n 60 'journalctl --disk-usage'

八、监控与告警

8.1 关键监控指标

1
2
3
4
5
6
7
8
9
10
11
# 日志磁盘使用率
journalctl --disk-usage | awk '{print $4}'

# 日志条目数量
journalctl --since "1 hour ago" | wc -l

# 服务状态
systemctl is-active systemd-journald

# 错误日志数量
journalctl -p err --since "1 hour ago" | wc -l

8.2 Prometheus 监控

使用 systemd_exporter 或 node_exporter:

1
2
3
4
5
# journald 磁盘使用
node_filesystem_size_bytes{mountpoint="/var/log/journal"}

# 日志速率
rate(journald_entries_total[5m])

8.3 告警规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# prometheus 告警规则
groups:
- name: journald
rules:
- alert: JournaldDiskHigh
expr: node_filesystem_avail_bytes{mountpoint="/var/log/journal"} / node_filesystem_size_bytes{mountpoint="/var/log/journal"} < 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "Journald 磁盘空间不足"

- alert: JournaldServiceDown
expr: up{job="node-exporter"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "systemd-journald 服务异常"

九、最佳实践

9.1 配置建议

场景 Storage MaxUse Retention
开发环境 volatile 500M 1d
生产环境 persistent 4G 14d
合规环境 persistent 10G 90d+

9.2 日志规范

1
2
3
4
5
6
7
8
9
# 推荐的服务日志配置
[Service]
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

# 结构化日志格式
# 应用应输出键值对格式
# KEY=VALUE 格式便于查询

9.3 安全建议

  • 限制日志目录权限(仅 root 和 systemd-journal 组可写)
  • 定期审计日志访问
  • 敏感信息脱敏后再记录
  • 配置远程日志备份

9.4 运维清单

1
2
3
4
5
6
7
8
9
10
11
12
# 日常检查
□ journalctl --disk-usage # 磁盘使用
□ systemctl status systemd-journald # 服务状态
□ journalctl -p err --since today # 今日错误

# 周检查
□ journalctl --vacuum-time=7d # 清理旧日志
□ 检查日志轮转是否正常

# 月检查
□ 审查日志配置是否需要调整
□ 验证备份和归档流程

十、总结

systemd-journald 是现代 Linux 系统的核心日志组件,掌握其故障排查方法对运维工作至关重要。

关键要点:

  1. 理解存储模式(persistent/volatile)对日志持久化的影响
  2. 合理配置磁盘配额和保留时间,避免磁盘耗尽
  3. 熟练使用 journalctl 进行日志查询和过滤
  4. 定期监控日志系统健康状态
  5. 建立日志备份和归档机制

参考文档: