代码仓
中
持久化问题定位方法
更新时间: 2025/10/29
在AtomGit上查看源码

1 查看持久化数据库内容 ​

确认数据有没有落盘到持久化最直观的方式是查看持久化数据库内容。

  • datas.yaml中配置的预置数据,在没有修改过的情况下,不会落盘到持久化数据库

1.1 一键收集 ​

release版本只能通过一键收集查看持久化数据库内容,收集后持久化数据存放在 dump_info\AppDump\persistence 目录下,每种持久化类型的数据导出到一个json文件,可以通过表名进行搜索

1.2 命令行查询 ​

临时持久化、复位持久化、掉电持久化数据库是sqlite数据库,可以使用sqlite3命令行工具执行sql语句进行查询(需要root权限,可以升级telnet破解包后查询)。

远程持久化数据存放路径如下:

远程持久化类型路径
临时持久化(TemporaryPer)/run/persistence/per_temporary.db
复位持久化(ResetPer)/opt/bmc/pram/persistence/per_reset.db
掉电持久化(PoweroffPer)/data/trust/persistence/per_poweroff.db
永久持久化(PermanentPer)/dev/mmcblk0p8

本地持久化(配置了"tableLocation": "local")数据存放路径如下:

本地持久化类型路径
临时持久化(TemporaryPer)/dev/shm/persistence.local/*.db
复位持久化(ResetPer)/opt/bmc/pram/persistence.local/*.db
掉电持久化(PoweroffPer)[非最小系统组件]/data/opt/bmc/persistence.local/*.db
掉电持久化(PoweroffPer)[最小系统组件]/data/trust/persistence.local/*.db
  • 可以通过环境上的 /opt/bmc/trust/mini_system.json 文件查看最小系统组件清单

1.2.1 临时持久化 ​

远程持久化:

bash
/usr/sbin/sqlite3 /run/persistence/per_temporary.db "SELECT * FROM persist_table WHERE table_name = 't_iptables_nat' ;"

本地持久化(数据库文件名是组件名称):

bash
/usr/sbin/sqlite3 /dev/shm/persistence.local/hwdiscovery.db "SELECT * FROM 't_hw_component' ;"

1.2.2 复位持久化 ​

远程持久化:

bash
/usr/sbin/sqlite3 /opt/bmc/pram/persistence/per_reset.db "SELECT * FROM persist_table WHERE table_name = 't_soc_management' ;"

本地持久化(数据库文件名是组件名称):

bash
/usr/sbin/sqlite3 /opt/bmc/pram/persistence.local/fault_diagnosis.db "select * from t_system_ras"

1.2.3 掉电持久化 ​

远程持久化:

按表名查询数据

bash
/usr/sbin/sqlite3 /data/trust/persistence/per_poweroff.db "SELECT * FROM persist_table WHERE table_name = 't_banner_config';"

本地持久化(数据库文件名是组件名称):

非最小系统组件

bash
/usr/sbin/sqlite3 /data/opt/bmc/persistence.local/cooling.db "select * from t_inlet_temp_record"

最小系统组件

bash
/usr/sbin/sqlite3 /data/trust/persistence.local/maca.db "select * from t_package"

1.2.4 永久持久化 ​

永久持久化数据以json格式存放在字符设备/dev/mmcblk0p8中,可以通过hexdump命令查看

永久持久化不支持本地持久化

bash
busybox hexdump -n 1048576 /dev/mmcblk0p8 -C

2 查看内存数据库内容 ​

在开启了基于mds的属性持久化特性,并且skynet进程开启了debug_console的前提下,可以通过注入代码方式查看组件内存数据库内容。

下面以查看组件bmc_time内存数据库的t_time_config表格为例

  • 1) 在data分区下创建lua文件(例如/data/test.lua),填入以下内容
lua
local c_object_manage = require 'mc.orm.object_manage'
local cjson = require 'cjson'
local sqlite3 = require 'lsqlite3'
local db = c_object_manage.get_instance().db.db
local vm = db:prepare('SELECT * FROM t_time_config')
while vm:step() ~= sqlite3.DONE do
    print(cjson.encode(vm:get_named_values()))
end
vm:finalize()
  • 2) 找到对应进程的debug_console端口号

可以在manifest仓库查看对应子系统的launch_control.json文件;

例如,bmc_time组件在bmc_core子系统,对应的debug_console端口号是40020:

  • 3)telnet连接debug_console,找到服务地址

telnet连接到环境IP,使用第2步找到的debug_console端口号

先执行list命令,找到组件对应的服务地址

  • 4)注入代码,查看输出

执行inject 服务地址 lua文件注入代码,查看内存数据库内容

3 调试方法 ​

3.1 删除数据 ​

以下介绍开发调试时,破解环境之后如何删除持久化数据

3.1.1 远程持久化 ​

远程持久化指的是MDS类定义没有配置tableLocation: Local,通过persistence服务统一管理的持久化方式

3.1.1.1 用sqlite命令行工具 ​

组件通过内存数据库间接读写远程持久化数据,如果用sqlite命令直接删除持久化数据库内容,删除后需要重启组件所在进程才能生效 (例如hardware进程下的组件,删除之后执行systemctl restart hardware) 临时、复位、掉电持久化可以对相应的数据库文件的persist_table执行sql语句删除数据。

以下命令以掉电持久化数据库为例

  • 删除整表数据示例(t_banner_config表所有数据):
bash
/usr/sbin/sqlite3 /data/trust/persistence/per_poweroff.db "DELETE FROM persist_table WHERE table_name = 't_banner_config';"
  • 删除表中某条记录示例(t_banner_config表中Id为1的记录):
bash
/usr/sbin/sqlite3 /data/trust/persistence/per_poweroff.db "DELETE FROM persist_table WHERE table_name = 't_banner_config' AND prime_key = 'Id:1';"
  • 删除表中某条记录某个属性值示例(t_banner_config表中Id为1的Content属性值):
bash
/usr/sbin/sqlite3 /data/trust/persistence/per_poweroff.db "DELETE FROM persist_table WHERE table_name = 't_banner_config' AND prime_key = 'Id:1' AND persist_param='Content';"

永久持久化存储在字符设备,不能用sqlite命令删除数据,只能通过注入代码进行删除

3.1.1.2 注入代码 ​

组件如果开启了ORM特性,可以通过skynet debug console注入代码操作内存数据库进行删除(框架通过钩子触发持久化数据库同步删除,不需要重启进程)。

例如,删除bmc_network组件的t_iptables_ipv4_nat表数据,可以注入以下代码进行数据删除(注入代码具体操作见上文章节)

lua
local c_object_manage = require 'mc.orm.object_manage'
local cjson = require 'cjson'
local sqlite3 = require 'lsqlite3'
local db = c_object_manage.get_instance().db
db:delete(db.tables['t_iptables_ipv4_nat']):exec()

3.1.2 本地持久化 ​

本地持久化指的是MDS类定义配置了tableLocation: Local,通过组件自行管理的持久化方式。

组件直接操作本地持久化数据库,不经过内存数据库映射,可以直接对本地持久化数据库文件执行sqlite命令进行数据删除,删除后立即生效不需要重启进程

例如,删除hwdiscovery组件的掉电本地持久化数据库表t_hw_component:

  • 删除整表数据示例(t_hw_component表所有数据):
bash
/usr/sbin/sqlite3 /data/trust/persistence.local/hwdiscovery.db "DELETE FROM t_hw_component;"
  • 删除单条记录示例(t_hw_component表中主键值Position等于01010A的记录):
bash
/usr/sbin/sqlite3 /data/trust/persistence.local/hwdiscovery.db "DELETE FROM t_hw_component WHERE Position='01010A';"

注意:对于存在新增字段的本地持久化数据表,删除时需要使用表名加_v_前缀的视图名,否则扩展表会存在数据残留

因为本地持久化新增字段是存储在扩展表,组件需要对主表和扩展表联合构成的视图进行操作。 代码中对local_db.类名映射的数据表进行操作时,框架已对视图进行封装,但直接通过表名来删除数据时仍需要使用带_v_前缀的视图名而不是原表名。

新增字段可以通过自动生成的local_db.lua中的extend_field()来鉴别。

例如,event组件的t_event_list_en表存在新增字段,删除时需要使用视图名_v_t_event_list_en

bash
/usr/sbin/sqlite3 /data/opt/bmc/persistence.local/event.db "DELETE FROM _v_t_event_list_en;"

3.2 恢复删除过的datas.yaml预置数据 ​

远程持久化删除过的数据,在数据库中的deleted_data_table保留主键值记录。组件初始化加载datas.yaml预置数据到内存数据库时,会将这部分已删除的数据去掉。如果调试时需要恢复删除过的datas.yaml预置数据,则需要手动删除deleted_data_table中对应表格的记录。

例如,恢复掉电持久化表t_manager_account的datas.yaml预置数据,可以执行以下命令,然后重启组件所在进程

bash
/usr/sbin/sqlite3 /data/trust/persistence/per_poweroff.db "DELETE FROM deleted_data_table WHERE table_name = 't_manager_account';"

常见问题 ​

关于持久化机制使用过程中的常见问题,请参考《持久化机制常见问题》进行处理。