日志收集工具:dmesg、journalctl 与串口捕获
做嵌入式安全启动,第一步不是看代码,而是学会“听”系统说话。日志就是系统的语言。你听不懂,出了问题就只能干瞪眼。
这一章,我带你搞定三个最常用的日志收集工具。它们分别是:dmesg(内核日志)、journalctl(系统日志)和串口捕获(硬件级日志)。这三板斧用熟了,大部分启动问题你都能定位个七七八八。
核心观点:日志收集不是“看输出”,而是“有目的地抓取”。不同阶段用不同工具,才能拿到最关键的线索。
1. dmesg:内核的“黑匣子”
dmesg 读取的是内核环形缓冲区。说白了,就是内核在启动过程中打印的所有信息。从 BootROM 交棒给内核,到驱动加载、文件系统挂载,全在这里。
我个人习惯,拿到一块新板子,第一件事就是跑 dmesg | head -50。为什么?因为我要确认内核版本、编译时间、以及早期有没有致命错误。
常用命令速查
| 命令 | 作用 | 我的经验 |
|---|---|---|
dmesg |
打印所有内核日志 | 信息太多,建议配合 grep |
dmesg -T |
显示人类可读时间戳 | 必加!否则你看不懂时间 |
dmesg -l err |
只显示错误级别日志 | 排查问题第一步 |
dmesg -w |
实时监控新日志 | 类似 tail -f,调试驱动时很爽 |
dmesg -c |
清空缓冲区 | 慎用!清完就没了 |
我的小技巧:在安全启动调试中,我经常用 dmesg -T | grep -i "secure\|trust\|verified\|dm-verity" 来快速定位与安全相关的日志。这样能一眼看出签名校验是否通过。
日志级别过滤
内核日志有 8 个级别,从 KERN_EMERG(0)到 KERN_DEBUG(7)。你想想看,如果启动时系统直接挂了,你还在看 debug 信息,那不是浪费时间吗?
我建议这样用:
# 只看错误和警告
dmesg -l err,warn
# 只看关键信息
dmesg -l crit,alert,emerg
# 查看某个模块的日志(比如 USB)
dmesg -T | grep -i usb
嗯,这里要注意:-l 参数后面可以跟多个级别,用逗号隔开就行。
2. journalctl:systemd 时代的日志瑞士军刀
如果你的系统用了 systemd(现在大部分嵌入式 Linux 都用了),那 journalctl 就是你的主力工具。它比 dmesg 更强大,因为它能记录用户态服务的日志,而不仅仅是内核的。
我记得第一次用 journalctl 时,被它的参数数量吓到了。但别慌,常用的其实就那几个。
核心用法
| 命令 | 作用 | 实战场景 |
|---|---|---|
journalctl -u sshd |
查看某个服务的日志 | SSH 连不上?看这个 |
journalctl -k |
查看内核日志(类似 dmesg) | 比 dmesg 多了索引 |
journalctl -p err |
按优先级过滤 | 只看错误,省眼睛 |
journalctl --since "1 hour ago" |
按时间过滤 | 出问题后回头看 |
journalctl -f |
实时跟踪日志 | 调试时开着,像 tail -f |
我曾经踩过的坑:journalctl 默认只保留最近的日志。如果系统重启了,之前的日志可能就丢了。解决办法是配置 /etc/systemd/journald.conf 中的 Storage=persistent,并设置 SystemMaxUse=500M。否则你重启后查不到上一轮的日志,那叫一个抓狂。
实战:排查安全启动服务
假设你的安全启动由一个叫 secure-boot-check 的服务负责。你可以这样查:
# 查看该服务的所有日志
journalctl -u secure-boot-check
# 只看最近的 20 条
journalctl -u secure-boot-check -n 20
# 加上时间戳和输出格式
journalctl -u secure-boot-check -o short-precise
# 实时监控
journalctl -u secure-boot-check -f
为什么我喜欢用 -o short-precise?因为它会显示微秒级的时间戳。在分析启动时序问题时,这个精度能帮你判断哪个服务先报错。
3. 串口日志捕获:最后的救命稻草
当系统连网络都没有,或者内核还没起来时,dmesg 和 journalctl 都救不了你。这时候,串口就是你的“上帝视角”。
说白了,串口日志是硬件级别的。只要 CPU 的 UART 引脚有输出,你就能看到从 BootROM 开始的所有信息。包括安全启动的签名校验、密钥加载、以及早期初始化失败的原因。
常用工具对比
| 工具 | 特点 | 适用场景 |
|---|---|---|
| minicom | 经典,功能全 | 日常调试,支持文件传输 |
| screen | 轻量,系统自带 | 快速连接,不想装软件 |
| picocom | 极简,无依赖 | 嵌入式环境,资源受限 |
| putty (Windows) | 图形化,支持串口 | Windows 开发机 |
我的串口配置模板
我个人习惯用 screen,因为它几乎每个 Linux 发行版都自带。配置如下:
# 连接串口(波特率 115200,8 数据位,1 停止位,无校验)
screen /dev/ttyUSB0 115200
# 退出:Ctrl+A,然后按 :quit
# 如果想记录日志到文件
screen -L -Logfile boot_log.txt /dev/ttyUSB0 115200
避坑指南:我曾经在调试一块 RK3588 开发板时,串口死活没输出。折腾了半天,发现是 USB 转串口模块的 TX/RX 接反了。嗯,这种低级错误最容易让人怀疑人生。记住:TX 接 RX,RX 接 TX,GND 接 GND。
波特率的选择
大部分嵌入式设备默认用 115200。但有些老旧的 bootloader 可能用 57600 甚至 9600。如果你看到乱码,先别慌,试试切换波特率。
我建议这样排查:
- 先试 115200,这是最常用的
- 如果乱码,试 57600
- 还不行?试 38400、19200、9600
- 如果所有波特率都是乱码,检查硬件连接
实战:一次安全启动的日志捕获流程
好了,理论说完了。我带你走一遍实际流程。假设我们要调试一块新板子的安全启动:
# 第一步:打开串口,捕获从 BootROM 开始的日志
screen -L -Logfile secure_boot_log.txt /dev/ttyUSB0 115200
# 第二步:给板子上电,观察输出
# 你会看到类似这样的信息:
# BootROM start
# Loader from eMMC
# Verify signature... OK
# Jump to kernel...
# 第三步:系统启动后,用 dmesg 看内核日志
dmesg -T | grep -i "secure\|trust"
# 第四步:用 journalctl 看安全服务日志
journalctl -u secure-boot-check -o short-precise
关键点:串口日志能捕获到 BootROM 阶段的签名校验信息,这是 dmesg 和 journalctl 做不到的。所以,做安全启动调试,串口是必备的。
总结一下
这三个工具各有分工:
- dmesg:看内核启动过程,适合驱动和内核模块调试
- journalctl:看系统服务日志,适合用户态服务排查
- 串口:看从 BootROM 开始的完整启动链,适合底层和安全启动调试
我个人建议,平时开发时三个工具都开着。串口一直录着,dmesg 和 journalctl 按需查询。这样一旦出问题,你手里有完整的日志链,定位起来会快很多。