Android log相关文档索引:
使用ADB命令控制logcat日志本地存储功能-CSDN博客
Android系统通过属性设置来控制log输出的方案-CSDN博客
Android系统设置kernel log level的方法-CSDN博客
使用ADB命令控制logcat日志本地存储功能
1. 需求背景
在 Android 系统上进行开发调试时,为了分析 bug,很多场景需要抓取开机log。
使用GUI界面的工程模式/开发者选项可以打开 logcat 日志的本地存储功能,从而可以很方便的抓取完整的开机日志。但是,当某些关键服务没能正常启动时,图形界面也很可能一直处于黑屏状态,导致无法通过屏幕操作进入到 工程模式/开发者选项 来启用日志存储;
因此对于无法进入工程模式GUI界面的场景需要一种方式,在不进行界面操作或切换 USB mode的情况下,也能启用 logcat 日志的本地存储。
2. 通过命令行控制
在命令行环境下,通过直接修改下列属性值,就可以打开/关闭 logcat 日志本地存储功能。
1.1 打开日志存储功能
setprop logd.logpersistd.enable true
setprop persist.logd.logpersistd.buffer all
setprop persist.logd.logpersistd logcatd
和通过工程模式/开发者选项打开日志存储功能一样,修改上述属性值后,可以在 /data/misc/logd/
目录下找到日志文件。 日志文件目录结构如下:
msmnile_gvmq:/ # ls /data/misc/logd
event-log-tags logcat logcat.001 logcat.002 logcat.003 logcat.id
1.2 关闭日志存储功能
setprop logd.logpersistd clear
setprop persist.logd.logpersistd.buffer ""
setprop logd.logpersistd.buffer ""
setprop logd.logpersistd.enable false
1.3 可能存在的问题
在某些情况下,也会出现以上命令无法开关 logcat 日志存储功能的情况。有可能是 selinux 权限未开放导致的。 可以尝试用 setenforce 0
命令解除权限限制后再尝试上述命令修改属性值;也有可能是特定Android系统中对persist.logd.logpersistd
这个属性进行了重新定义造成的,可搜索这个属性在代码中的位置,跟踪分析原因。
1.4 其它
对于 logd.logpersistd
和 persist.logd.logpersistd
这种命名很相似的属性,他们的什么区别和联系,可以从代码中关于各属性的描述进程查看。此外,从文件 logcatd.rc 中,也能发现二者的关联:
......
on property:persist.logd.logpersistd=logcatd
setprop logd.logpersistd logcatd
......
on property:logd.logpersistd.enable=true && property:logd.logpersistd=logcatd
# log group should be able to read persisted logs
mkdir /data/misc/logd 0750 logd log
start logcatd
# stop logcatd service and clear data
on property:logd.logpersistd.enable=true && property:logd.logpersistd=clear
setprop persist.logd.logpersistd ""
stop logcatd
# logd for clear of only our files in /data/misc/logd
exec - logd log -- /system/bin/logcat -c -f /data/misc/logd/logcat -n ${logd.logpersistd.size:-256}
setprop logd.logpersistd ""
# stop logcatd service
on property:logd.logpersistd=stop
setprop persist.logd.logpersistd ""
stop logcatd
setprop logd.logpersistd ""
on property:logd.logpersistd.enable=false
stop logcatd
......
文件格式比较简单,意图也很清楚,就是在各属性值发生变化时分别执行哪些操作。
3. logd 支持的完整属性列表
除了上文提到的属性,logd
还能对别的属性值变化产生响应。 完整的属性列表可以在 Google 官方文档找到,见 /system/logging/logd/README.property。
不过原文档的说明比较简洁,所以现将其部分翻译、并补充说明如下:
属性名 | 属性值类型 | 默认值 | 描述 |
ro.logd.auditd | bool | TRUE | 允许/禁止 selinux 相关日志通过 logcat 打印。 |
ro.logd.auditd.dmesg | bool | TRUE | 将 selinux 相关日志打印到 dmesg 缓冲区。 |
ro.logd.auditd.main | bool | TRUE | 将 selinux 相关日志打印到 main 缓冲区。 |
ro.logd.auditd.events | bool | TRUE | 将 selinux 相关日志打印到 events 缓冲区。 |
persist.logd.security | bool | FALSE | Enable security buffer. |
ro.organization_owned | bool | FALSE | Override persist.logd.security to false |
ro.logd.kernel | bool | svelte+ | 允许/禁止内核日志通过 logcat 打印。 |
logd.statistics | bool | svelte+ | 如果该属性值为 true,那么可以通过 logcat -S 命令查看日志统计信息。 |
ro.debuggable | number | 如果该属性值不为 "1",那么 logd.statistics 和 ro.logd.kernel 属性的值将被置为 false。 | |
logd.logpersistd.enable | bool | auto | 启动 logcatd 进程的“保险开关”。一般不需手动设置。属性值必须为 true 才能打开日志本地存储功能。 |
logd.logpersistd | string | persist | 将该属性值设置为 "logcatd" 可启动 logcatd 进程,同时打开日志本地存储功能。 等同于 logcat -f 命令的效果。 |
也可以设置属性值为 "clear" 或 "stop",实现日志文件清零或关闭日志本地存储功能。 | |||
logd.logpersistd.buffer | persist | 选择将哪些日志缓冲区的数据要存储到本地文件。 | |
属性值可以是 "all", "main", "system", "radio", "events", "crash"。当系统为 userdebug 或 eng 版本时,还可以设置为 "kernel"。 | |||
logd.logpersistd.size | persist | 设置本地存储日志文件的总大小,单位为 MB。 | |
logd.logpersistd.rotate_kbytes | persist | 设置本地存储的单个日志文件的大小,单位为 KB。 | |
persist.logd.logpersistd | string | 将该属性值设置为 "logcatd" 可启动 logcatd 进程,同时打开日志本地存储功能。 等同于 logcat -f 命令的效果。 | |
persist.logd.logpersistd.buffer | all | 选择将哪些日志缓冲区的数据要存储到本地文件。 | |
属性值可以是 "all", "main", "system", "radio", "events", "crash"。当系统为 userdebug 或 eng 版本时,还可以设置为 "kernel"。 | |||
persist.logd.logpersistd.size | 256 | 设置本地存储日志文件的总大小,单位为 MB。即 persist.logd.logpersistd.rotate_kbytes 与 persist.logd.logpersistd.count 的乘积。无需手动调整。 | |
persist.logd.logpersistd.count | 256 | 设置本地存储的日志文件个数,最多不超过 [count] 个。 | |
persist.logd.logpersistd.rotate_kbytes | 1024 | 设置本地存储的单个日志文件的大小,单位为 KB。 | |
persist.logd.size | number | ro | 系统启动后,各日志缓冲区(main, system, radio 等)的默认大小。 |
运行时,可以通过另一个命令加以修改: logcat -b all -G [value] | |||
ro.logd.size | number | svelte | persist.logd.size 属性的默认值。 |
如果该属性值超过 256KB,那么在日志打印过多(多到近乎 spam )的情况下, logcatd 偶尔会工作异常。 这种情况下,请优先考虑删除代码中的垃圾日志打印,而不是增加该属性值的大小。 | |||
persist.logd.size.[buffer] | number | ro | 设置 [buffer] 日志缓冲区的大小。 [buffer] 可以是 main、system、radio 等。 |
ro.logd.size.[buffer] | number | svelte | persist.logd.size.[buffer] 的默认值。 |
ro.config.low_ram | bool | FALSE | 如果该属性值为 true,那么 logd.statistics 和 ro.logd.kernel 属性的值将被置为 false,且 logd.size 属性的值将被置为 64K。 |
persist.logd.filter | string | 设置日志删减规则。 | |
运行时,也可以通过另一个命令加以修改: logcat -P "[string]" | |||
ro.logd.filter | string | "~! ~1000/!" | persist.logd.filter 属性的默认值。 |
默认值 ~! ~1000/! 的含义是 “从指定的 UID 组里,找出打印日志最频繁的进程,将其还未打印的日志中等待时间最长的日志条目从打印队列中剔除/删减。1000 就是 AID_SYSTEM 的意思”。 | |||
log.tag | string | persist | 设置全局日志打印级别。 |
可以设置的级别有 VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, SILENT。 | |||
只需要将属性值设置为某个级别的首字母即可。 | |||
persist.log.tag | string | build | log.tag 属性的默认值。 |
log.tag.[tag] | string | persist | 设置 [tag] 对应的代码的日志打印级别。 |
检查源文件中是否包含语句 #define LOG_TAG "tag",其中 "tag" 可以任意指定。 | |||
persist.log.tag.[tag] | string | build | log.tag.[tag] 属性的默认值。 |
logd.buffer_type | string | (empty) | 设置日志缓冲区的类型。 属性值可以是 'simple', 'chatty', 'serialized'。 |
如果该属性值为空,等同于 'chatty'。 |
表中术语说明:
术语 | 说明 |
auto | 表示该属性值由 init 进程自动管理。 |
svelte | see ro.config.low_ram for details. |
svelte+ | 表示如果该属性值未被设置,且 ro.config.low_ram == false && ro.debuggable == true,那么默认为 true。 |
ro | [base property] temporary override, ro.[base property] platform default. |
persist | [base property] override, persist.[base property] platform default. |
build | VERBOSE for native, DEBUG for jvm isLoggable, or developer option. |
number | 表示该属性值为数值类型。 |
为方便使用,值类型为 number 的属性允许使用 “数字 + K/M” 形式进行赋值,比如 setprop persist.logd.size.main 1M 表示将 main buffer 大小设置为 1M 字节。 | |
日志缓冲区大小的可设置范围是 64K 到 256M。 | |
日志缓冲区可以是 main、system、radio 等等。 | |
"~! ~1000/!" | 表示一条日志删减规则。其中数字部分代表 UID 或 PID,格式为 UID/PID。例如 1000/ 表示对 UID 同为 1000 的所有进程打印的日志进行删减;/546 表示对 PID 为 546 的进程打印的日志进行删减;1000/546 表示对 UID 为 1000 且 PID 为 546 的进程打印的日志进行删减。 |
在规则中添加 ~ 前缀表示以高优先级删减根据 UID/PID 匹配到的日志条目,否则以低优先级进行删减。 | |
对于优先级相同的待删减日志条目,更老的条目会被先删减掉。 | |
特殊语法 ~! 表示根据 logd 统计信息,自动对打印日志最频繁的 UID 组中的待打印日志进行删减。 | |
示例中的语法 ~1000/! 表示如果当前打印日志最猖狂的 UID 组是 1000,那么将对组内打印日志最多的进程的日志进行删减。 |