首页 > 其他分享 >通过命令行启用 logcat 日志本地存储功能

通过命令行启用 logcat 日志本地存储功能

时间:2023-12-11 14:23:43浏览次数:33  
标签:logcat logpersistd logd 命令行 persist 日志 ro 属性

注意:本文基于 Android 12 进行分析
Qidi 2023.12.06 (MarkDown & Haroopad)


0. 背景

在 Android 系统上进行开发时,为了分析 bug,有些时候我们需要抓取开机日志。

很多人知道,通过界面操作进入 开发者选项 就可以打开 logcat 日志的本地存储功能,从而很方便的抓取完整的开机日志。但是,当 Java 层有某些关键服务没能正常启动时,图形界面也很可能一直处于黑屏状态,导致无法通过屏幕操作进入到 开发者选项 来启用日志存储。

有人说那我们还可以提前执行 adb logcat 命令,再对设备上电,一样可以抓到完整开机日志。没错,大多数设备上是可以这样操作。但是,对于某些设备来说, 要么仅有一个 USB 接口,还被某个外设占用了,无法同时用于外设连接和 ADB 连接;要么虽然有多个 USB 接口,但必须等系统启动后手动将 USB 切换到 devices 模式后,才能进行 ADB 连接。这种情况下,就算提前执行 adb logcat 命令,但因为找不到设备,所以也无法抓取到开机日志。

因此我们需要一种方式,在不进行界面操作或切换 USB Role 的情况下,也能启用 logcat 日志的本地存储。


1. 通过命令行控制

在命令行环境下,通过直接修改下列属性值,就可以打开/关闭 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 命令解除权限限制后再尝试上述命令修改属性值。

1.4 其它

对于 logd.logpersistdpersist.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
......

文件格式比较简单,意图也很清楚,就是在各属性值发生变化时分别执行哪些操作。我就不一一解释了。


2. 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.statisticsro.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"。当系统为 userdebugeng 版本时,还可以设置为 "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"。当系统为 userdebugeng 版本时,还可以设置为 "kernel"。
persist.logd.logpersistd.size 256 设置本地存储日志文件的总大小,单位为 MB。即 persist.logd.logpersistd.rotate_kbytespersist.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.statisticsro.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,那么将对组内打印日志最多的进程的日志进行删减。

标签:logcat,logpersistd,logd,命令行,persist,日志,ro,属性
From: https://www.cnblogs.com/qidi-huang/p/how_to_enable_android_logcat_local_storages_by_comman

相关文章

  • ConcurrentModificationException日志关键字报警引发的思考
    本文将记录和分析日志中的ConcurrentModificationException关键字报警,还有一些我的思考,希望对大家有帮助。一、背景近期,在日常的日志关键字报警分析时,发现我负责的一个电商核心系统在某时段存在较多ConcurrentModificationException异常日志,遂进行分析和改进,下面是我的一些思考......
  • Grafana系列-Loki-基于日志实现告警
    系列文章Loki系列文章前言实际应用中除了基于Metrics告警,往往还有基于日志的告警需求,可以作为基于Metrics告警之外的一个补充.典型如基于NGINX日志的错误率告警.本文将介绍如何基于Loki实现基于日志的告警.本文我们基于以下2类实际场景进行实战演练:基于......
  • allure commandline 命令行参数
    一、allurehtml产生流程方法一:alluregenerate+allureopen方法二:allureserver二、语法格式generateopenserver参考资料本文地址:https://www.cnblogs.com/hchengmx/p/17892977.html一、allurehtml产生流程Step1.test文件运行后产生allure-results文......
  • Amazon如何日志实践的?
    1深入研究日志第一次工作遇到代码报错尝试解决并没有做好,而且我不清楚是哪里做错了。一位同事建议我打开日志看看是哪里出错了。而要这样做,他说我应该“cat日志文件”。当时我真以为同事们在和我开玩笑,或者在说一个关于猫的笑话,只不过我没听懂。我在大学里使用Linux只是为了......
  • 提升生产力:是时候升级你的命令行工具了
    命令行的历史可以追溯到Unix操作系统的起源,也就是1969年,Unix诞生之时,前辈们就已经用命令行来和操作系统交互了。随着计算机性能的飞速发展,图形化的操作界面逐渐成为主流,命令行工具离普通用户越来越远。这些年来,图形界面的发展不仅仅表现在界面越来越美观,其操作方式也越来越丰富,不......
  • oracle日志模式
    oracle日志模式一、oracle日志模式分为(logging,forcelogging,nologging)默认情况是logging,就是会记录到redo日志中,forcelogging是强制记录日志,nologging是尽量减少日志。FORCELOGGING可以在数据库级别、表空间级别进行设定、而LOGGING与NOLOGGING可以在表级别设定。注:FORCELOGGIN......
  • Windows 11 cmd命令行修改背景色、设置指定图片、桌面背景
    前言全局说明Windows11cmd命令行修改背景色、设置指定图片、桌面背景一、找到设置--外观可以自定义图片,也可以使用桌面背景图片(二选一)如果设置图片位置或高、宽,没有达到你想要的,可以在“拉伸模式”、“图像对齐”设置二、设置不透明度1.设置背景100%透明度效果......
  • springboot集成log4j日志
    一、在springboot的pom.xml配置文件中引入依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><!--排除默认spring-boot-starter-logging启动器-->......
  • 计划任务与日志
    [root@localhost~]#systemctlenablecrond[root@localhost~]#psaux|grepcrondroot62420.30.01263801656?Ss16:270:00/usr/sbin/crond-ncrond进程每分钟会处理一次计划任务存储位置[root@localhost~]#ls/var/spool/cron......
  • 读程序员的README笔记05_日志、监控与配置
    1. 行为准则2. 日志分级2.1. 日志框架设有日志级别,它可以让运维人员根据重要性过滤消息2.2. 编程语言有精良的日志类库,让运维人员对要记录的内容和时间有更多的控制2.3. TRACE2.3.1. 一个极其精细的日志级别2.3.2. 对特定的包或类开放2.3.3. 在开发阶段之外很少......