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。我个人习惯用相对时间,因为不用算时区。
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 的核心用法串起来了。建议你保存下来,忘了就瞄一眼。
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% 的日常问题。