7.2.8 Log 使用指南
Log 系统分区规划
Log 分区
| 分类 | log 类型 | 存储位置 | 单个 log 最大大小 | log 文件数量 | 是否压缩 | 内容 |
|---|---|---|---|---|---|---|
| 基础系统 log | kernel | /var/log/ | NA | 4 | 是 | 内核、驱动、syslog 的 log 信息 |
| 基础系统 log | pstore | /log/pstore | 4M | 100 | 否 | 内核 crash 的 log 信息 |
| 基础系统 log | coredump | /log/coredump | NA | NA | 否 | 应用 crash 的 coredump 文件,目录大小限制2G |
| 基础系统 log | coredump | /log/stackdump | NA | 20 | 否 | 应用 crash 的 log 信息 |
| 基础系统 log | remoteproc | /log/dsp0 | 1M | 200 | 否 | DSP0固件输出的 log 信息 |
| 基础系统 log | remoteproc | /log/bl31 | 1M | 200 | 否 | BL31固件输出的 log 信息 |
| 基础系统 log | remoteproc | /log/optee | 1M | 200 | 否 | optee 固件输出的 log 信息 |
| 基础系统 log | remoteproc | /log/mcu* | 2M | 200 | 否 | mcu 固件输出的 log 信息 |
| 基础系统 log | remoteproc | /log/bpu0 | 1M | 200 | 否 | bpu0固件输出的 log 信息 |
| 基础系统 log | remoteproc | /log/hsm | 1M | 200 | 否 | hsm 固件输出的 log 信息 |
| 基础系统 log | remoteproc | /log/uboot | 8KB | 100 | 否 | uboot 输出的 log 信息 |
| 基础系统 log | reset | /log/reset_reason.txt | 1M | 1 | 否 | 记录每次系统启动原因 |
| 基础系统 log | reset | /log/reset_count.txt | 4KB | 1 | 否 | 记录当前系统重启次数 |
| ALOG 系统 | ALOG | /log/usr | 2M | 200 | 否 | ALOG 接口的 log 信息 |
| systemd | journal | /log/journal | NA | NA | 否 | systemd journal,总大小约100MB |
Log 内容
-
Kernel Log
- 内核 log:通过 rsyslog 转存到
/var/log/目录下 - pstore
log:当内核 crash 重启时,移动
/sys/fs/pstore目录日志到/log/pstore目录下,记录系统 panic 前后的内核日志
- 内核 log:通过 rsyslog 转存到
-
启动原因 log
- reset_reason.txt 信息介绍:
- poweroff:断电后等待30s 后正常上电(零下10度以下需要断电时间更长)
- hwreset:拉 reset pin 重启
- ddrtrainfail:ddr training 失败重启
- pmicwdt:pmic watchdog 重启
- mreboot:mcu 正常重启
- mpanic:mcu panic 重启
- mwdt:系统各种原因导致的 hang 住引起的 watchdog 复位
- mhlost:Acore 丢心跳重启
- deepsleep:深睡眠重启
- lightsleep:浅睡眠唤醒
- scpreboot:scp 正常重启
- splreboot:spl 正常重启
- splpanic:spl panic 重启
- freboot:bl31正常重启
- fpanic:bl31 panic 重启
- oreboot:optee 正常重启
- opanic:optee panic 重启
- ureboot:uboot 正常重启
- upanic:uboot panic 重启
- kreboot:kernel 正常重启
- kpanic:kernel panic 重启
- lmbistfail:硬件 bist 失败重启
- sblpanic:sbl panic 重启
- mbdiso:bdiso 错误重启
- offsleep:main off + mcu sleep 重启
- mainreboot:main reboot 重启
- invalidtemp:异常温度重启
- reset_count.txt:当前系统重启次数,0到9999循环计数
- reset_reason.txt 信息介绍:
-
remoteproc log
- dsp*:dsp*固件输出的 log 信息
- bl31:bl31固件输出的 log 信息
- optee:optee 固件输出的 log 信息
- mcu:mcu 固件输出的 log 信息
- bpu*:bpu*固件输出的 log 信息
- hsm:hsm 固件输出的 log 信息,加密保存
- uboot:uboot 输出的 log 信息
-
ALOG 系统
- 使用 libalog 库的 pr_*接口打印的 log 信息
- 应用软件推荐使用 libalog 库的 pr_*接口
-
systemd journal log
- systemd 运行过程中的日志,目前配置大小100MB,实际占用会更大,大约达到102MB
- systemd journal 在应对异常掉电、系统时间异常等情况时,可能会出现丢失本次启动日志的情况
-
应用 crash log
- coredump:储存进程在突然崩溃那一刻的内存快照,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在该目录文件中,量产建议关闭
- stackdump:debug 版本开启,储存 systemd 服务进程在突然崩溃那一刻的状态信息,占用空间小
Log 管理
Log 进程
-
进程信息
- 板端 log 进程运行信息如下,不同设备的 log 进程有所区别,以实际命令结果为准:
root@ubuntu:/userdata# ps -ef | grep log | grep -v -e grep -e login -e dbus-daemon
root 1083 1 0 11:16 ? 00:00:00 /bin/bash /usr/bin/hobot-log
root 1514 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start bl31
root 1518 1514 0 11:16 ? 00:00:00 hrut_remoteproc_log -b /dev/bl31_log_dev -f /log/bl31/message -r 1024 -n 200
root 1520 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start bpu0
root 1521 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start dsp0
root 1523 1520 0 11:16 ? 00:00:00 hrut_remoteproc_log -b /proc/bpu0_msg -f /log/bpu0/message -r 1024 -n 200
root 1525 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-init-hb_hsm_log_server.sh
root 1526 1521 0 11:16 ? 00:00:00 hrut_remoteproc_log -b /sys/class/remoteproc/remoteproc_vdsp0/log -f /log/dsp0/message -r 1024 -n 200
root 1527 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start logcat
root 1529 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start mcu
root 1530 1527 0 11:16 ? 00:00:00 logcat -v time -f /log/usr/message -r2048 -n 200
root 1531 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start optee
root 1536 1529 0 11:16 ? 00:00:00 hrut_remoteproc_log -b /proc/remoteproc_mcu0 -f /log/mcu0/message -r 2048 -n 200
root 1538 1525 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start hsm
root 1539 1 0 11:16 ? 00:00:00 python3 /usr/bin/hobot-log-rename.py /log -m auto
root 1541 1529 0 11:16 ? 00:00:00 hrut_remoteproc_log -b /proc/remoteproc_mcu1 -f /log/mcu1/message -r 2048 -n 200
root 1542 1 0 11:16 ? 00:00:00 /usr/hobot/bin/syslogd -n -O /log/kernel/message -s 2048 -b 200
root 1545 1 0 11:16 ? 00:00:00 /bin/sh /usr/bin/hobot-log-start klogd
root 1546 1538 0 11:16 ? 00:00:00 hsm_log -f /log/hsm/message -r 1024 -n 200
root 1547 1531 0 11:16 ? 00:00:00 optee_log -f /log/optee/message -r 1024 -n 200-
kernel: rsyslog
- 获取内核记录的消息,将消息数据转存到文件中
-
usr: ALOG(libalog.so)和 logcat
- 通过 ALOG 接口 pr_*向 log buffer 写入 log 信息,logcat 从 log buffer 中获取 log 信息,将其写入文件中
-
remoteproc_log:hrut_remoteproc_log、hsm_log、optee_log 进程
- 通过 remoteproc 节点获取 MCU,DSP,BL31,BPU,HSM,OPTEE 的 log 信息,将其写入文件中
-
日志管理:hobot-log 和 hobot-log-rename.py
-
log 记录:记录 reset,pstore,uboot 的 log 信息
-
log 管理:定期每10分钟将原始 log 文件转存成固定格式文件,管控各个分区目录的存储空间, 超过固定容量会进行删除,删除时间比较早产生的文件
-
-
启动顺序
-
hobot-log-daemon.service 服务开机自启,启动 hobot-log 守护进程,去启动相关 log 服务,并管理日志,启动顺序如下:
|- /usr/bin/hobot-log
|- record_reset_count(shell function)
|- record_reset_reason(shell function)
|- message_rotate_and_add_resetcount(shell function)
|- wait_for_timesync(shell function)
|- set_pstore(shell function)
|- set_uboot(shell function)
|- systemd_journal_config(shell function)
|- check_first_log(shell function)
|- 启动相关log服务,启动各 个模块日志记录进程
|- hobot-log-rename.py脚本进行日志重命名归档、空间管理
-
Log 管理方式
log 的文件生成和目录空间管控主要是由 hobot-log 和 hobot-log-rename.py 去管理的。
-
log 管理
-
容量管控:
- 在 hobot-log 脚本中配置了各个模块的日志文件大小和数量限制,这些限制会通过入参传递给各个模块日志进程。每个模块日志文件限制说明见:log分区
- 各个模块的进程管理各自的日志文件大小和数量限制,超过限制后会删除产生时间比较早的文件
-
log 文件重命名归档:
- 启动时,转存 uboot 和 pstore log,命名格式如下:
- SuperSoC_Uboot-count-time.Log:当系统启动时,将 uboot log 转存到 uboot 的 archive 目录下
- SuperSoC_Pstore-count-time(文件夹):当系统启动时,如果检测到上次系统是异常重启,则创建该格式文件夹,并将对应的异常 log 信息记录到该文件夹下
- 运行时,log 文件通过 hobot-log-rename.py 进程重命名归档,每10分钟各模块目录下的 message.*文件重命名归档到模块的 archive 目录下,并根据容量管控删除 archive 目录下旧文件
- 该进程由 hobot-log-rename.service 服务启动,根据 hobot-log 生成的配置文件
/log/hb_log_rename.conf管理各模块 - 如果不希望运行过程中重命名日志文件,通过修改
hbre/boot-utils/hb-init-scripts/DEBIAN/postinst文 件,关闭该服务自启 - 关闭后如果还希望对当前的 log 文件重命名归档,可以手动执行如下命令:
python3 /usr/bin/hobot-log-rename.py /log -m manual - log 文件重命名格式如下:
- 示例:SuperSoC_Usr-0003~2025_05_06_08_01_00_131599.Log
- 命名说明:[board]_[module]-[count]-[time]_<inode>.Log
- board:SuperSoC
- module:Usr,Uboot,Pstore 等首字母大写
- count:4位数字,0000到9999,示例中代表第3次重启
- time:如2025_05_06_08_01_00
- inode:如131599,但正常情况下没有,只有当出现同一秒转存多个文件命名存在重合时,加入 inode 号来做区分
- 该进程由 hobot-log-rename.service 服务启动,根据 hobot-log 生成的配置文件
- 启动时,转存 uboot 和 pstore log,命名格式如下:
-
内核日志使用 ubuntu 系统自带的 rsyslog 服务管理,因此这里对内核 log 管理方式做单独介绍。
- 容量管控:
- 不会限制单个 kern.log 的大小
- 日志每周进行一次轮转
- 系统最多保留4个历史日志文件
- log 归档:
- 当日志轮转发生时,当前日志文件会按照编号进行重命名归档。归档原则:kern.log 达到轮转周期,logrotate 将 kern.log 重命名为 kern.log.1,创建新的 kern.log,rsyslog 继续写入日志。当超过最大数量限制后,最开始产生的日志文件会被删除
- 为减少磁盘占用,系统会对历史日志进行压缩。压缩策略:最近一次轮转日志延迟一轮再解压缩
- 参数配置:
- 如果用不想使用 ubuntu 默认配置参数来配置日志管理策略,可以通过修改
/etc/logrotate.d/rsyslog文件中的配置实现。
{
rotate 4 //最大保留历史日志文件个数
weekly //轮转周期
missingok //如果日志丢失,不报错继续滚动下一个日志
notifempty //当前日志为空时,不进行轮转
compress //通过gzip压缩
delaycompress //和compress一起使用时,转储的日志文件到下一次转储时才压缩
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
} - 如果用不想使用 ubuntu 默认配置参数来配置日志管理策略,可以通过修改
- 容量管控:
-
-
定制 log 系统
- log 大小和数量修改
- 日志大小在 hobot-log 中修改,修改
ROTATESIZE和ROTATESIZE_REMOTE变量的定义,单位是 KB - 日志数量在 hobot-log 中修改,修改
ROTATEGENS_USR、ROTATEGENS_REMOTE、UBOOT_LOGMAX、PSTORE_LOGMAX变量的定义,对应的分别是 usr、remoteproc_log、uboot、pstore 的日志数量限制,当前值分别是200、200、100、100 - systemd journal
log 大小配置在源码
debian/source/scripts/general.sh脚本中修改 SystemMaxUse 值,同时需要注意文件大小 SystemMaxFileSize 和文件数量 SystemMaxFiles 限制相乘要大于 SystemMaxUse
- 日志大小在 hobot-log 中修改,修改
- log 命名修改
- 当前命名规范是[board]_[module]-[count]-[time]_<inode>.Log,在 hobot-log 脚本中修改前缀和尾缀,即[board]_[module]和.Log。在 hobot-log-rename.py 脚本中修改[count]和[time],涉及
get_reset_count和get_file_time两个函数
- 当前命名规范是[board]_[module]-[count]-[time]_<inode>.Log,在 hobot-log 脚本中修改前缀和尾缀,即[board]_[module]和.Log。在 hobot-log-rename.py 脚本中修改[count]和[time],涉及
- log 进程的裁剪
-
可以通过增减 systemd 的 log service,来增减 log 进程,通过修改
hbre/boot-utils/hb-init-scripts/DEBIAN/postinst文件实现。部分 log 相关服务如下:/etc/systemd/system/basic.target.wants/hobot-log-bl31.service
/etc/systemd/system/basic.target.wants/hobot-log-bl31-timesync.service
/etc/systemd/system/basic.target.wants/hobot-log-bpu0.service
/etc/systemd/system/basic.target.wants/hobot-log-daemon.service
/etc/systemd/system/basic.target.wants/hobot-log-dsp0.service
/etc/systemd/system/basic.target.wants/hobot-log-hsm.service
/etc/systemd/system/basic.target.wants/hobot-log-logcat.service
/etc/systemd/system/basic.target.wants/hobot-log-mcu.service
/etc/systemd/system/basic.target.wants/hobot-log-optee.service -
以 hobot-log-logcat.service 为例,介绍设备端如何控制 log 服务启停:
# 开启服务开机自启
systemctl enable hobot-log-logcat.service
# 关闭服务开机自启
systemctl disable hobot-log-logcat.service
# 查看服务状态
systemctl status hobot-log-logcat.service
# 启动服务
systemctl start hobot-log-logcat.service
# 停止服务
systemctl stop hobot-log-logcat.service
-
- log 大小和数量修改
-
log 时间
- hobot-log 提供了等待时间同步完成的功能,以确保日志中的时间戳准确。该功能可通过
YEAR_LIMIT 和 WAIT_FOR_TIMESYNC_TIMEOUT 两个变量进行配置,分别用于设定时间同步成功的阈值以及超时时间。需要注意的是,Debian 系统的默认时间为其发行版本的发布时间。因此,在每次更新 Debian 版本时,应相应修改YEAR_LIMIT的值,使其大于该版本的发布时间。通常情况下,将其配置为最新日期即可。
- hobot-log 提供了等待时间同步完成的功能,以确保日志中的时间戳准确。该功能可通过
Log 接口使用推荐
Kernel
- 在驱动中推荐使用如下接口 dev_err, dev_warn, dev_info, dev_dbg。
- 没有设备结构的场合使用如下接口 pr_error, pr_warn, pr_info, pr_debug。
- pr_debug,dev_dbg 可通过如下方法动态开启。
echo "file drivers/mmc/host/* +p" > /sys/kernel/debug/dynamic_debug/controlecho "module mmc_core +p" > /sys/kernel/debug/dynamic_debug/controlecho "func mmc_detect_change +p" > /sys/kernel/debug/dynamic_debug/control
- 对于出错后可能重复非常多次的打印,用如 下接口。
- printk_once: 只打印一次
- printk_ratelimited: 限制每秒打印次数,默认每5秒最多打印10次
- 内核敏感地址打印方法。
- 内核敏感地址使用%pK 替代%p,
配置
/proc/sys/kernel/kptr_restrict为2后,打印地址为全0
- 内核敏感地址使用%pK 替代%p,
配置
应用程序
-
推荐使用 pr 的接口,对应的打印级别有
pr_verbose、pr_debug、pr_info、pr_warn、pr_err、pr_fatal、pr_verbose_with_tag、pr_debug_with_tag、pr_info_with_tag、pr_warn_with_tag、pr_err_with_tag、pr_fatal_with_tag。 -
使用 pr* 接口时,各个模块在输出 Log 时,可以通过定义 LOG_TAG 宏来打印自身模块名,logcat 支持使用 tag 筛选日志。其可通过 Makefile 传入,如:
DLOG_TAG=camera;或者在代码开头声明。 -
使用 pr* _tag 接口时,各个模块在输出 Log 时,可以通过第一个参数来打印自身模块名,logcat 支持使用 tag 筛选日志。
-
log 系统支持1个2MB 的 log_main 缓冲区,1个256KB 的 log_radio 缓冲区,建议使用 log_main 缓冲区。
- 当 LOG_TAG 是"HTC_RIL"、"RIL"、"IMS"、"AT"、"GSM"、"STK"、"CDMA"、"PHONE"、"SMS"时,日志保存到 log_radio 缓冲区,其他的都保存到 log_main 缓冲区。
-
代码示例和测试结果如下:
//gcc logtest.c -o logtest -L . -lalog -I /usr/hobot/include/
#define LOG_TAG "alog_test"
#include <stdio.h>
#include <logging.h>
int main(int argc, char **argv)
{
pr_verbose("*ALOG test start*n");
pr_debug("********1********n");
pr_info("********2********n");
pr_warn("********3********n");
pr_err("********4********n");
pr_verbose("*ALOG test end***n");
return 0;
}# 测试结果:
root@ubuntu:/# ./logtest
# 不设置过滤:
root@ubuntu:/# logcat
logcat test start !!!
--------- beginning of /dev/log_main
V/alog_test(21590): *ALOG test start*
D/alog_test(21590): ********1********
I/alog_test(21590): ********2********
W/alog_test(21590): ********3********
E/alog_test(21590): ********4********
V/tag (21590): ********1********
D/tag (21590): ********1********
I/tag (21590): ********2********
W/tag (21590): ********3********
E/tag (21590): ********4********
F/tag (21590): ********1********
V/alog_test(21590): *ALOG test end***
设置过滤-s *:F
root@ubuntu:/# logcat -s *:F
logcat test start !!!
--------- beginning of /dev/log_main
F/tag (21590): ********1********
设置过滤-s *:E
root@ubuntu:/# logcat -s *:E
logcat test start !!!
--------- beginning of /dev/log_main
E/alog_test(21590): ********4********
E/tag (21590): ********4********
F/tag (21590): ********1********
设置过滤-s tag:E
root@ubuntu:/# logcat -s tag:E
logcat test start !!!
--------- beginning of /dev/log_main
E/tag (21590): ********4********
F/tag (21590): ********1********
MCU
LogSync/LogNotice/LogAsync接口支持将 log 输出到串口以及转存到 Acore。
其中,转存到 Acore 的临时文件节点在:/proc/remoteproc_mcu0和/proc/remoteproc_mcu1,Acore 会启动 hrut_remoteproc_log 进程周期性的获取 proc 节点中的日志写入/log/mcu*的 messag 文件实现转存。
由于单个文件可以存储的日志大小有限,加上重启后上一次存储的 message 日志会被启动的 log 进程重写覆盖。所以实现了 log 管理机制支持对 log 文件重命名归档,具体描述 见:log管理。
- LogSync 用于同步打印优先级较低的日志。
在 debug 镜像中使用 LogSync 接口,日志会正常输出到串口和转存到 Acore。在 release 镜像中不会向串口输出,只保留转存到 Acore 的功能。
- LogNotice 用于同步打印优先级较高的日志。
LogNotice 无论是在 debug 还是 release 镜像,日志都会正常输出到串口和转存到 Acore。
- LogAsync 用于异步打印。
LogAsync 输出原则同 LogSync。
接口使用说明
编译路径添加Service/Log,代码引用Service/Log/Common/inc/下的头文件Log.h,即可调用 LogSync、LogNotice 以及 LogAsync 接口。
串口打印和转存 Acore 的功能由Service/Log/Config/inc/Log_Cfg.h中的两个宏LOG_SEND_TO_UART和LOG_SEND_TO_ACORE控制:
#define LOG_SEND_TO_ACORE (STD_ON)
#ifdef MCU_RELEASE
#define LOG_SEND_TO_UART (STD_OFF) // LogSync 和 LogAsync 打印到串口通路关闭,必要信息将通过 LogNotice 临时开启串口通路来打印。
#else
#define LOG_SEND_TO_UART (STD_ON) // LogSync、LogNotice以及LogAsync 打印到串口通路始终开启。
#endif
MCU Log 使用注意事项,请参考:MCU Log简介。
DSP
- 推荐使用
DSP_ERR、DSP_WARN、DSP_INFO、DSP_DBG接口。
Log 使用注意
Log 调试注意点
- 调试时大量日志可 以单独保存,防止丢失,方便查看
- 内核日志:
dmesg -w > /userdata/dmesg.log & - ALOG 日志:
logcat -v time -f /userdata/logcat.log &
- 内核日志:
- 每个转存周期(10min)内产生超过 rotate 数量的日志会造成日志丢失
- 首先应只输出必要的日志
- 如果输出较多 log,在设置 rotate 的数量时候,要考虑好所需大小
- 不要在串口、ssh 窗口实时查看日志。可能会发现丢日志,原因是输出慢,覆盖导致。如果必须,建议 ssh 窗口实时查看日志。
- 比如使用 logcat 在串口实时查看输出,内核若输出"logcat lost message",则说明有日志丢失。
- S100日志写入存储设备保存。考虑到存储设备的寿命有限和大量存储日志对
IO/CPU 性能的影响,应只输出必要的日志,正式版本不应输出大量调试日志。
- 比如当 S100 存储设备是 eMMC(64GB、MLC、3000次擦写)时,若每分钟写入10MB 日志,则连续工作十年消耗27%寿命,考虑写入放大,消耗更多。
- S600日志写入存储设备保存。考虑到存储设备的寿命有限和大量存储日志对
IO/CPU 性能的影响,应只输出必要的日志,正式版本不应输出大量调试日志。
- 比如当 S600 存储设备是 eMMC(64GB、MLC、3000次擦写)时,若每分钟写入10MB 日志,则连续工作十年消耗27%寿命,考虑写入放大,消耗更多。
logcat 使用
- logcat 命令格式
| # | 参数 | 描述 |
|---|---|---|
| 1 | -b <buffer> | 加载一个可使用的日志缓冲区供查看,比如 event 和 radio,默认值是 main |
| 2 | -c | 清除缓冲区中的全部日志并退出(清除完后可以使用 -g 查看缓冲区) |
| 3 | -d | 将缓冲区的 log 转存到屏幕中然后退出 |
| 4 | -f <filename> | 将 log 输出到指定的文件 <filename>,默认为标准输出(stdout) |
| 5 | -g | 打印日志缓冲区的大小并退出 |
| 6 | -n <count> | 设置日志的最大数目 <count>,默认值是 4,需要和 -r 选项一起使用 |
| 7 | -r <kbytes> | 每输出 <kbytes> 时轮替日志文件,默认值是 16,需要和 -f 选项一起使用 |
| 8 | -s | 设置过滤器 |
| 9 | -v <format> | 设置日志消息的输出格式,默认是短格式 |
Log debug
死机情况如何保存有效日志记录
- 在出现系统 panic 死机的时候,pstore 的机制是可以将发生 panic 的内核 log 信息存储到 pstore 的目录中的,但 BL31和 mcu 的 panic 信息没法保存,需要注意。
有效获取问题时刻日志
- 在 log 分区中的文件的命名字段中包含对应 log 文件的最后修改时间的信息,可以去文件中查找问题时刻的 log。