4. systemd 日志系统:从入门到实战
聊到 Linux 日志,很多人第一反应是 /var/log/messages。但在我日常排障中,systemd-journald 才是真正的利器。它把内核日志、系统服务日志、用户应用日志全部收拢到一起,用 journalctl 一把抓。今天我就带你把它吃透。
一句话总结:systemd 日志系统 = journald(采集引擎)+ journalctl(查询工具)。它比传统 syslog 更结构化、更安全、更易查。
4.1 journalctl 基础用法
先来个最直接的——看所有日志:
journalctl
这命令会输出从开机到现在所有日志,量很大。我一般不会这么用,而是加参数过滤。
4.1.1 按时间过滤
排障时最常用的就是看“刚才发生了什么”。比如:
# 查看本次启动以来的日志
journalctl -b
# 查看上一次启动的日志(排重启故障时很有用)
journalctl -b -1
# 只看最近 10 分钟的
journalctl --since "10 min ago"
# 指定时间范围
journalctl --since "2025-03-01 08:00" --until "2025-03-01 12:00"
我个人习惯用 --since "1 hour ago" 这种相对时间,省得算时区。
4.1.2 按服务/单元过滤
想看某个服务的日志?加 -u:
# 只看 sshd 的日志
journalctl -u sshd
# 同时看两个服务
journalctl -u nginx -u mysql
我曾经遇到一个 case:Nginx 频繁 502,但错误日志里啥也没有。用 journalctl -u nginx -f 实时跟踪,才发现是 upstream 的 PHP-FPM 进程被 OOM killer 干掉了。嗯,这种跨服务的关联,传统日志文件很难一眼看出来。
4.1.3 实时跟踪与翻页
# 类似 tail -f
journalctl -f
# 分页查看(默认行为,适合阅读)
journalctl | less
# 输出最后 50 行
journalctl -n 50
小技巧:排障时我常用 journalctl -u <服务名> -f --since "5 min ago",既能看到历史,又能实时跟踪新日志。
4.2 日志优先级:一眼识别严重程度
日志不是平起平坐的。systemd 沿用了 syslog 的 8 级优先级,从 0(emerg)到 7(debug)。你想想看,生产环境里如果满屏都是 debug 信息,真正的问题就被淹没了。
| 优先级 | 数值 | 含义 | 典型场景 |
|---|---|---|---|
| emerg | 0 | 系统不可用 | 内核 panic、系统崩溃 |
| alert | 1 | 必须立即处理 | 磁盘损坏、数据库损坏 |
| crit | 2 | 严重错误 | 硬件故障、服务完全不可用 |
| err | 3 | 错误 | 配置错误、连接失败 |
| warning | 4 | 警告 | 磁盘空间不足、重试成功 |
| notice | 5 | 正常但重要 | 服务启动/停止、用户登录 |
| info | 6 | 一般信息 | 请求处理、状态更新 |
| debug | 7 | 调试信息 | 开发/排障时使用 |
用 -p 参数按优先级过滤:
# 只看 err 及以上级别(0-3)
journalctl -p err
# 只看 warning 及以上(0-4)
journalctl -p warning
# 指定范围:只看 err 到 crit
journalctl -p err..crit
避坑指南:我曾经在生产环境用 journalctl -p debug 查问题,结果日志量太大直接把终端卡死了。建议先 -n 100 限制行数,或者配合 --since 缩小时间范围。
4.3 日志字段解析:结构化数据的威力
传统日志是一行字符串,你得靠正则去抠信息。systemd 日志不一样——每条日志都是一组 结构化字段(key=value)。这才是它最强大的地方。
4.3.1 查看完整字段
# 显示所有字段(verbose 模式)
journalctl -u sshd -o verbose
# 输出示例(部分字段)
_TRANSPORT=syslog
_PID=1234
_UID=0
_GID=0
_COMM=sshd
_EXE=/usr/sbin/sshd
_CMDLINE=/usr/sbin/sshd -D
_SYSTEMD_UNIT=sshd.service
_BOOT_ID=abc123...
MESSAGE=Accepted publickey for root from 192.168.1.100 port 22
PRIORITY=6
SYSLOG_FACILITY=10
4.3.2 常用字段速查
| 字段名 | 含义 | 排障用途 |
|---|---|---|
MESSAGE |
日志正文 | 核心信息 |
PRIORITY |
优先级(0-7) | 过滤严重级别 |
_PID |
进程 ID | 追踪具体进程 |
_UID |
用户 ID | 判断是哪个用户触发的 |
_SYSTEMD_UNIT |
所属 systemd 单元 | 定位到具体服务 |
_BOOT_ID |
启动 ID | 区分不同启动周期 |
_TRANSPORT |
日志来源(syslog/stdout/kernel) | 判断日志产生方式 |
_CMDLINE |
完整命令行 | 确认启动参数 |
4.3.3 按字段过滤
这才是 journalctl 的杀手锏:
# 找 PID 为 1234 的进程日志
journalctl _PID=1234
# 找某个用户触发的日志
journalctl _UID=1000
# 组合过滤:找 sshd 服务中 PID 为 1234 的日志
journalctl _SYSTEMD_UNIT=sshd.service _PID=1234
# 找内核日志
journalctl _TRANSPORT=kernel
你想想看,传统方式要查“某个 PID 在某个时间段的日志”,得 grep 半天。用 journalctl 一条命令搞定。
4.4 日志持久化:别让日志丢了
默认情况下,journald 把日志存在内存(/run/log/journal)。好处是快,不伤磁盘。坏处是——重启就没了。
我记得有一次排查一个“开机后服务启动失败”的问题,因为日志没持久化,重启后现场全丢了,只能靠猜。从那以后,我所有服务器都做了持久化配置。
4.4.1 开启持久化
创建持久化目录,然后重启服务:
# 创建持久化目录
mkdir -p /var/log/journal
# 设置正确的权限
systemd-tmpfiles --create --prefix /var/log/journal
# 重启 journald
systemctl restart systemd-journald
验证是否生效:
# 查看日志存储路径
journalctl --header | grep "Journal path"
# 正常输出应该是
# Journal path: /var/log/journal/机器ID/system.journal
4.4.2 配置日志大小与保留策略
持久化后要注意磁盘空间。我见过有人没配限制,结果日志把根分区撑爆了。配置文件在 /etc/systemd/journald.conf:
[Journal]
# 日志最大体积(默认 10% 分区大小)
SystemMaxUse=500M
# 单个日志文件最大
SystemMaxFileSize=100M
# 保留最近 2 周的日志
MaxRetentionSec=2week
# 日志文件达到上限后,删除最旧的 20%
SystemKeepFree=20%
改完配置记得重启:
systemctl restart systemd-journald
我的建议:生产环境配 SystemMaxUse=1G + MaxRetentionSec=1month,既能保留足够长的历史,又不会撑爆磁盘。如果日志量特别大(比如业务日志),建议单独分一个分区给 /var/log。
4.4.3 手动清理日志
有时候磁盘告警了,需要紧急腾空间:
# 只保留最近 3 天的
journalctl --vacuum-time=3d
# 只保留 200M 日志
journalctl --vacuum-size=200M
# 只保留最近 5 个日志文件
journalctl --vacuum-files=5
4.5 知识体系总览
下面这张图把 systemd 日志系统的核心脉络串起来了,建议你保存下来当速查表:
4.6 实战排障场景
最后分享一个我常用的排障流程,遇到服务异常时按这个顺序查:
- 看服务状态:
systemctl status <服务名>—— 先确认是不是 systemd 层面的问题 - 看最近日志:
journalctl -u <服务名> -n 50 --since "30 min ago"—— 缩小范围 - 看错误级别:
journalctl -u <服务名> -p err --since "1 hour ago"—— 只看关键错误 - 看关联服务:
journalctl _PID=<异常PID> -o verbose—— 深挖具体进程 - 看系统整体:
journalctl -p emerg..err -b—— 检查本次启动有没有系统级问题
这套流程我用了好几年,90% 的服务故障都能在 5 分钟内定位到根因。你试试看,用熟了之后,你会觉得传统日志文件就像回到了石器时代。