3、日志系统基础:slogger与slog2info、日志级别与过滤、日志持久化配置

说到QNX的日志系统,我不得不先感慨一句——这玩意儿真的是嵌入式调试的「眼睛」。没有它,很多线上问题你根本无从下手。今天咱们就聊聊slogger和slog2info这对黄金搭档,以及怎么用好日志级别和持久化。

3.1 slogger:QNX的日志守护进程

slogger是什么?说白了,它就是QNX系统里的一个后台服务,专门负责收日志、存日志、转发日志。你想想看,如果每个进程都自己往硬盘上写日志,那不乱套了?slogger就是那个统一管理的「日志总管」。

我个人习惯,在项目启动脚本里第一个启动的就是slogger。为什么?因为后面的服务如果出问题,我需要第一时间看到日志。

核心要点:slogger是一个守护进程,它从各个进程接收日志消息,然后根据配置决定是写到内存缓冲区、写到文件,还是通过网络发出去。

启动slogger很简单,通常这样搞:

# 启动slogger,使用默认配置
slogger &

# 或者指定配置文件
slogger -f /etc/slogger.conf &

嗯,这里要注意——slogger本身不能产生日志,它只是个「收件箱」。真正发日志的是各个应用程序,它们通过调用slog2库函数把消息扔给slogger。

3.2 slog2info:查看日志的瑞士军刀

日志收进来了,怎么看?slog2info就是干这个的。我刚开始用QNX那会儿,经常在终端里敲slog2info,然后被满屏的日志刷到眼花缭乱。

最基本的用法:

# 查看所有日志
slog2info

# 实时跟踪日志(类似tail -f)
slog2info -w

但是,真正让我觉得slog2info强大的是它的过滤能力。我在项目中遇到过一个问题——系统里几百个进程都在打日志,我想只看某个模块的日志怎么办?

# 只看进程ID为123的日志
slog2info -i 123

# 只看某个程序名的日志
slog2info -c my_app

# 只看某个级别的日志(后面会细说级别)
slog2info -l 4

小技巧:我经常用slog2info -w结合grep来实时过滤。比如slog2info -w | grep "ERROR",这样只显示错误级别的日志,排查问题效率高很多。

3.3 日志级别:从0到7的学问

QNX的日志级别沿用了syslog的标准,一共8个级别。数字越小越严重:

级别编号 级别名称 说明 我一般怎么用
0 EMERG 紧急,系统不可用 内核panic、硬件故障
1 ALERT 必须立即处理 关键资源耗尽
2 CRIT 严重错误 模块崩溃前兆
3 ERROR 一般错误 函数调用失败
4 WARNING 警告 非预期但可恢复
5 NOTICE 正常但重要 状态切换、配置变更
6 INFO 一般信息 日常运行信息
7 DEBUG 调试信息 开发阶段用,上线关掉

你可能会问:为什么要有这么多级别?我曾经在一个项目里吃过亏——所有日志都用INFO级别,结果线上出问题时,几万条INFO日志里翻那几条ERROR,简直大海捞针。从那以后,我严格要求团队:

  • 上线版本:只保留WARNING及以上级别
  • 测试版本:开到INFO级别
  • 开发调试:才开DEBUG

避坑指南:千万不要在生产环境开DEBUG级别!我曾经见过一个同事,上线忘了关DEBUG,结果slogger的缓冲区被DEBUG日志撑爆,导致真正的ERROR日志被冲掉了。排查了整整两天才发现这个低级错误。

3.4 日志过滤:精准定位问题

光有级别还不够,实际项目中我们经常需要更精细的过滤。slog2info提供了多种过滤方式:

# 按时间过滤:只看最近5分钟的日志
slog2info -t "-5m"

# 按进程名过滤
slog2info -c "can_server"

# 组合过滤:只看can_server的ERROR日志
slog2info -c "can_server" -l 3

我个人最常用的是按模块名过滤。在代码里,每个模块可以设置不同的日志标签:

// 代码中设置模块标签
slog2_buffer_t *buffer;
slog2_register("can_bus", &buffer);
slog2(buffer, 0, LOG_ERROR, "CAN总线通信超时");

然后在命令行里:

slog2info -b "can_bus"

这样就能只看CAN总线模块的日志,其他模块的日志一概不显示。排查问题的时候,这个功能简直是救命稻草。

3.5 日志持久化:让日志「活」下来

默认情况下,slogger把日志存在内存里。这有个问题——一旦系统重启,日志就没了。你想想看,如果系统崩溃了,重启后日志全丢了,你怎么分析原因?

所以,日志持久化是必须的。配置方法如下:

# /etc/slogger.conf 配置文件示例

# 设置日志文件路径
log_file /var/log/slogger.log

# 设置单个日志文件大小(单位:字节)
log_file_size 1048576  # 1MB

# 设置保留的日志文件数量
log_file_count 5

# 设置日志级别阈值(只记录3级及以上的日志)
log_filter_level 3

启动时指定配置文件:

slogger -f /etc/slogger.conf

我的经验:日志文件大小和数量要根据你的存储空间来定。我一般这样算:系统正常运行一天产生多少日志,然后乘以3(保留3天的量),再留点余量。比如一天产生10MB,那就设log_file_size=10M,log_file_count=5,这样能保留5天的日志。

还有一个容易被忽略的点——日志轮转。slogger自带了轮转机制,当文件达到上限时,会自动把旧文件重命名,然后新建一个文件继续写。比如:

slogger.log       # 当前正在写的
slogger.log.1     # 最旧的
slogger.log.2
slogger.log.3
slogger.log.4     # 最新的备份

嗯,这里要提醒一下——如果你的系统对写寿命有要求(比如用eMMC或NAND Flash),建议把日志写到内存文件系统(如/dev/shmem)里,然后通过一个定时任务把关键日志同步到持久存储。我有个项目就是这么干的,Flash的寿命延长了至少3倍。

3.6 实战:一个完整的日志配置示例

最后,我给大家一个我项目中实际用过的配置模板:

# /etc/slogger.conf
# 生产环境配置

# 日志文件路径
log_file /var/log/system.log

# 文件大小限制:5MB
log_file_size 5242880

# 保留5个备份
log_file_count 5

# 只记录ERROR及以上级别(0-3)
log_filter_level 3

# 缓冲区大小:64KB
buffer_size 65536

# 同步写模式(保证日志不丢)
sync_mode 1

启动命令:

slogger -f /etc/slogger.conf

查看日志:

# 实时查看ERROR日志
slog2info -w -l 3

# 查看某个模块的日志
slog2info -c "my_app" -l 3

好了,关于slogger和slog2info的基础知识就聊到这儿。说白了,日志系统就是你的「黑匣子」,配置好了能帮你省下大把排查问题的时间。下一节咱们聊聊更高级的日志分析技巧,到时候我会分享一个我亲手踩过的坑——怎么从海量日志里快速定位内存泄漏。