4. journalctl入门:从基本用法到高效过滤

说实话,很多运维干了三五年,还在用 tail -f /var/log/messages 看日志。systemd 时代早就来了,journalctl 才是你该掌握的利器。这一章,我带你把 journalctl 的基本功打扎实。

4.1 为什么是 journalctl?

传统日志是文本文件,一行一行追加。systemd 的 journal 是二进制格式,结构化了。好处很明显:

  • 自带索引:按时间、优先级、单元(unit)查,秒级响应
  • 元数据丰富:每条日志都带着 PID、UID、内核设施、来源文件
  • 不丢日志:即使程序崩溃,journal 也能把缓冲区的日志刷到磁盘

我刚开始从 syslog 切到 journalctl 时,也觉得多此一举。直到有一次排查内核 panic,传统日志文件被截断了,journal 里却保留了完整的环形缓冲区——嗯,从那以后我再也没回头。

4.2 基本用法:先跑起来

journalctl 最基础的用法,就是直接敲:

journalctl

这会输出所有日志,从系统启动到现在。量非常大,你想想看,一个跑了一周的服务器,可能几十万条。所以一般不会这么用。

常用变体:

命令 作用
journalctl -n 50 只看最近 50 条,类似 tail -n 50
journalctl -f 实时跟踪,类似 tail -f
journalctl -x 附带解释信息,把错误码翻译成人类语言
journalctl -o verbose 显示完整元数据,调试时特别有用
我的习惯: 每次登录服务器,先跑 journalctl -n 20 -x --no-pager,快速扫一眼最近有没有异常。20 条不占屏幕,-x 能直接看懂错误含义。

4.3 查看启动日志:定位开机问题

服务器起不来,或者启动慢,这是最常见的故障场景。journalctl 专门为启动日志做了设计。

查看本次启动的日志:

journalctl -b

查看上一次启动的日志:

journalctl -b -1

查看更早的启动:

journalctl -b -2   # 上上次
journalctl --list-boots  # 列出所有启动记录

--list-boots 的输出格式:

偏移 启动 ID 时间范围
-2 abc123... Mon 2024-01-15 08:00:00 CST → Mon 2024-01-15 18:30:00 CST
-1 def456... Mon 2024-01-15 19:00:00 CST → Tue 2024-01-16 03:15:00 CST
0 ghi789... Tue 2024-01-16 03:20:00 CST → 还在运行

我曾经遇到一台机器,每次重启都要 5 分钟。用 journalctl -b -1 对比正常启动的日志,发现某个服务在等待网络挂载超时。嗯,这就是典型的启动慢问题。

4.4 按时间过滤:精确到秒

时间过滤是 journalctl 最强大的功能之一。你不需要 grep 去翻整个文件。

常用时间格式:

# 查看今天
journalctl --since today

# 查看昨天
journalctl --since yesterday --until now

# 查看具体时间段
journalctl --since "2024-01-15 09:00:00" --until "2024-01-15 12:00:00"

# 相对时间(最近 1 小时)
journalctl --since "-1h"

# 从某个时间点到结束
journalctl --since "2024-01-15 09:00:00"

时间格式很灵活,支持 yesterday、today、now、-1h、-30m、-5min。我个人习惯用相对时间,因为不用算时区。

注意: journalctl 默认使用系统时区。如果你的服务器是 UTC,而你的思维是 CST(东八区),记得换算。我吃过这个亏,查了半天日志对不上时间。

4.5 按优先级过滤:只看关键信息

日志级别从 0 到 7,数字越小越严重。journalctl 支持按优先级过滤。

优先级 数字 含义 常见场景
emerg 0 系统不可用 内核 panic、系统崩溃
alert 1 必须立即处理 磁盘损坏、内存耗尽
crit 2 严重错误 服务崩溃、硬件故障
err 3 错误 配置错误、连接失败
warning 4 警告 磁盘即将满、重试次数过多
notice 5 正常但重要 服务启动、配置变更
info 6 信息 日常操作日志
debug 7 调试 开发阶段使用

过滤命令:

# 只看错误及以上(0-3)
journalctl -p err

# 只看警告及以上(0-4)
journalctl -p warning

# 只看紧急和严重错误
journalctl -p emerg -p alert

# 结合启动日志
journalctl -b -p err

这里有个细节:-p err 会包含 err、crit、alert、emerg 四个级别。说白了,就是「比 err 更严重的都给我看」。

实战技巧: 我排查问题时,通常先跑 journalctl -b -p err --no-pager。如果输出为空,说明系统层面没有严重错误,问题大概率在应用层。如果输出一堆,那就按时间戳一条一条看。

4.6 组合过滤:真正的效率

单独用时间或优先级还不够。真正的效率来自组合。

# 查看今天的所有错误
journalctl --since today -p err

# 查看最近 2 小时的警告及以上
journalctl --since "-2h" -p warning

# 查看本次启动中,sshd 服务的错误
journalctl -b -u sshd -p err

# 查看昨天 10 点到 12 点之间的内核日志
journalctl --since "2024-01-15 10:00" --until "2024-01-15 12:00" -k

你想想看,传统方式要 grep 多少文件?journalctl 一条命令搞定。

4.7 知识体系图

下面这张图,把 journalctl 的核心用法串起来了。建议你保存下来,忘了就瞄一眼。

journalctl 核心用法知识体系 journalctl 核心用法 journalctl 基本用法 启动日志 时间过滤 优先级过滤 -n 50 最近50条 -f 实时跟踪 -x 解释信息 -b 本次启动 -b -1 上次启动 --list-boots 列表 --since today --until "时间" --since "-1h" -p err -p warning -p emerg -p alert 组合过滤:效率翻倍 journalctl -b -u sshd -p err --since "-1h" 核心原则:先过滤再查看,不要裸跑 journalctl

4.8 避坑指南

最后,分享几个我踩过的坑:

  • 日志被持久化了吗? 默认 journal 日志存在内存里,重启就丢。需要配置 /var/log/journal 持久化。我有一台测试机没配,查历史启动日志时发现全是空的——嗯,白忙活。
  • 时间戳别搞混:journalctl 显示的是系统时区。如果你的服务器跨时区部署,记得用 --utc 参数统一成 UTC。
  • 日志量太大怎么办? 用 journalctl --vacuum-size=500M 限制日志大小,或者 --vacuum-time=2weeks 保留最近两周。
  • 不要用 grep 替代过滤:很多人习惯 journalctl | grep error,这会把所有日志拉到内存,效率极低。用 -p err 才是正道。
我的日常巡检脚本:
#!/bin/bash
# 检查本次启动的错误
journalctl -b -p err --no-pager | head -50
# 检查磁盘相关警告
journalctl -b -p warning --since "-1d" | grep -i "disk\|i/o\|mount"
# 检查 SSH 登录失败
journalctl -b -u sshd -p notice | grep "Failed"
这三条命令,基本能覆盖 80% 的日常问题。