使用ADB命令控制logcat日志本地存储功能

使用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.logpersistdpersist.logd.logpersistd 这种命名很相似的属性,他们的什么区别和联系,可以从代码中关于各属性的描述进程查看。此外,从文件 logcatd.rc 中,也能发现二者的关联:

......
on property:persist.logd.logpersistd=logcatdsetprop logd.logpersistd logcatd
......
on property:logd.logpersistd.enable=true && property:logd.logpersistd=logcatd# log group should be able to read persisted logsmkdir /data/misc/logd 0750 logd logstart logcatd# stop logcatd service and clear data
on property:logd.logpersistd.enable=true && property:logd.logpersistd=clearsetprop persist.logd.logpersistd ""stop logcatd# logd for clear of only our files in /data/misc/logdexec - 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=stopsetprop persist.logd.logpersistd ""stop logcatdsetprop logd.logpersistd ""on property:logd.logpersistd.enable=falsestop logcatd
......

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


3. logd 支持的完整属性列表

除了上文提到的属性,logd 还能对别的属性值变化产生响应。 完整的属性列表可以在 Google 官方文档找到,见 /system/logging/logd/README.property

不过原文档的说明比较简洁,所以现将其部分翻译、并补充说明如下:

属性名属性值类型默认值描述
ro.logd.auditdboolTRUE允许/禁止 selinux 相关日志通过 logcat 打印。
ro.logd.auditd.dmesgboolTRUE将 selinux 相关日志打印到 dmesg 缓冲区。
ro.logd.auditd.mainboolTRUE将 selinux 相关日志打印到 main 缓冲区。
ro.logd.auditd.eventsboolTRUE将 selinux 相关日志打印到 events 缓冲区。
persist.logd.securityboolFALSEEnable security buffer.
ro.organization_ownedboolFALSEOverride persist.logd.security to false
ro.logd.kernelboolsvelte+允许/禁止内核日志通过 logcat 打印。
logd.statisticsboolsvelte+如果该属性值为 true,那么可以通过 logcat -S 命令查看日志统计信息。
ro.debuggablenumber如果该属性值不为 "1",那么 logd.statistics 和 ro.logd.kernel 属性的值将被置为 false。
logd.logpersistd.enableboolauto启动 logcatd 进程的“保险开关”。一般不需手动设置。属性值必须为 true 才能打开日志本地存储功能。
logd.logpersistdstringpersist将该属性值设置为 "logcatd" 可启动 logcatd 进程,同时打开日志本地存储功能。 等同于 logcat -f 命令的效果。
也可以设置属性值为 "clear" 或 "stop",实现日志文件清零或关闭日志本地存储功能。
logd.logpersistd.bufferpersist选择将哪些日志缓冲区的数据要存储到本地文件。
属性值可以是 "all", "main", "system", "radio", "events", "crash"。当系统为 userdebug 或 eng 版本时,还可以设置为 "kernel"。
logd.logpersistd.sizepersist设置本地存储日志文件的总大小,单位为 MB。
logd.logpersistd.rotate_kbytespersist设置本地存储的单个日志文件的大小,单位为 KB。
persist.logd.logpersistdstring将该属性值设置为 "logcatd" 可启动 logcatd 进程,同时打开日志本地存储功能。 等同于 logcat -f 命令的效果。
persist.logd.logpersistd.bufferall选择将哪些日志缓冲区的数据要存储到本地文件。
属性值可以是 "all", "main", "system", "radio", "events", "crash"。当系统为 userdebug 或 eng 版本时,还可以设置为 "kernel"。
persist.logd.logpersistd.size256设置本地存储日志文件的总大小,单位为 MB。即 persist.logd.logpersistd.rotate_kbytes 与 persist.logd.logpersistd.count 的乘积。无需手动调整。
persist.logd.logpersistd.count256设置本地存储的日志文件个数,最多不超过 [count] 个。
persist.logd.logpersistd.rotate_kbytes1024设置本地存储的单个日志文件的大小,单位为 KB。
persist.logd.sizenumberro系统启动后,各日志缓冲区(main, system, radio 等)的默认大小。
运行时,可以通过另一个命令加以修改: logcat -b all -G [value]
ro.logd.sizenumbersveltepersist.logd.size 属性的默认值。
如果该属性值超过 256KB,那么在日志打印过多(多到近乎 spam )的情况下, logcatd 偶尔会工作异常。 这种情况下,请优先考虑删除代码中的垃圾日志打印,而不是增加该属性值的大小。
persist.logd.size.[buffer]numberro设置 [buffer] 日志缓冲区的大小。 [buffer] 可以是 main、system、radio 等。
ro.logd.size.[buffer]numbersveltepersist.logd.size.[buffer] 的默认值。
ro.config.low_ramboolFALSE如果该属性值为 true,那么 logd.statistics 和 ro.logd.kernel 属性的值将被置为 false,且 logd.size 属性的值将被置为 64K。
persist.logd.filterstring设置日志删减规则。
运行时,也可以通过另一个命令加以修改: logcat -P "[string]"
ro.logd.filterstring"~! ~1000/!"persist.logd.filter 属性的默认值。
默认值 ~! ~1000/! 的含义是 “从指定的 UID 组里,找出打印日志最频繁的进程,将其还未打印的日志中等待时间最长的日志条目从打印队列中剔除/删减。1000 就是 AID_SYSTEM 的意思”。
log.tagstringpersist设置全局日志打印级别。
可以设置的级别有 VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, SILENT。
只需要将属性值设置为某个级别的首字母即可。
persist.log.tagstringbuildlog.tag 属性的默认值。
log.tag.[tag]stringpersist设置 [tag] 对应的代码的日志打印级别。
检查源文件中是否包含语句 #define LOG_TAG "tag",其中 "tag" 可以任意指定。
persist.log.tag.[tag]stringbuildlog.tag.[tag] 属性的默认值。
logd.buffer_typestring(empty)设置日志缓冲区的类型。 属性值可以是 'simple', 'chatty', 'serialized'。
如果该属性值为空,等同于 'chatty'。

表中术语说明:

术语说明
auto表示该属性值由 init 进程自动管理。
sveltesee 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.
buildVERBOSE 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,那么将对组内打印日志最多的进程的日志进行删减。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/869203.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单链表(C语言详细版)

1. 链表的概念及结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表的结构跟火车车厢相似,淡季时车次的车厢会相应减少,旺季时车次的车厢会额外增加几节。…

3.结果映射ResultMap(关联association+collection)

结果映射ResultMap 一.结果映射 是 MyBatis 中最重要最强大的元素,简化代码,允许JDBC不支持的一些操作 1.常用属性 constructor - 用于在实例化类时,注入结果到构造方法中 (一般不用) idArg - ID 参数;标记出作为 ID 的结果可…

Day65 代码随想录打卡|回溯算法篇---组合总和II

题目(leecode T40): 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含…

Linux文件编程(打开/创建写入读取移动光标)

目录 一、如何在Linux下做开发 1.vi编辑器 2.gcc编译工具 3.常用指令 二、文件打开及创建 三、写入文件 四、读取文件 五、文件“光标”位置 一、如何在Linux下做开发 所谓文件编程,就是对文件进行操作,Linux的文件和Windows系统的文件大差不差…

Python函数 之 函数基础

print() 在控制台输出 input() 获取控制台输⼊的内容 type() 获取变量的数据类型 len() 获取容器的⻓度 (元素的个数) range() ⽣成⼀个序列[0, n) 以上都是我们学过的函数,函数可以实现⼀个特定的功能。我们将学习⾃⼰如何定义函数, 实现特定的功能。 1.函数是什么…

剑指offer,打印从1到最大的n位数

这道题重点考察的就是我们的大数打印,因为如果按照普通的整形去循环打印的话,碰见n10的情况下就会超出整形的范围了,所以我们使用字符串进行打印,确切的说是使用字符进行打印,代码如下所示: public static…

EtherCAT主站IGH-- 11 -- IGH之fmmu_config.h/c文件解析

EtherCAT主站IGH-- 11 -- IGH之fmmu_config.h/c文件解析 0 预览一 该文件功能`fmmu_config.c` 文件功能函数预览二 函数功能介绍1. `ec_fmmu_config_init`2. `ec_fmmu_set_domain_offset_size`3. `ec_fmmu_config_page`示例用法示例详细说明三 h文件翻译四 c文件翻译该文档修改…

数据库sql语句中exists关键字的用法及原理

一、EXISTS关键字是做什么的? EXISTS是SQL语句中的一个关键字,用于判断一个子查询是否返回了任何行。如果子查询返回的结果集非空,EXISTS返回TRUE,否则返回FALSE。 二、EXISTS的基本语法示例: SELECT column1, colu…

氛围感视频素材高级感的去哪里找啊?带氛围感的素材网站库分享

亲爱的创作者们,大家好!今天我们来聊聊视频创作中至关重要的一点——氛围感。一个好的视频,不仅要有视觉冲击力,还要能够触动观众的情感。那我们应该去哪里寻找这些充满氛围感且高级的视频素材呢?别急,我这…

打开IDEA,程序员思考的永远只有两件事!!!

微信公众号:牛奶 Yoka 的小屋 有任何问题。欢迎来撩~ 最近更新:2024/07/09 [大家好,我是牛奶。] 当年面试时背了很多八股文,但在日渐重复的机械工作中(产品业务开发),计算机网络、操作系统、算…

混合贪心算法求解地铁线路调度

一、问题描述 城市轨道交通的繁荣发展,带来了车辆资源需求的日益增加。如何兼顾运营服务水平和运营成本,以最少的车底优质地完成运输任务成为一大严峻问题。本题在后续的描述中将由多辆动车和拖车组合而成的车组称为车底。在日常的运营组织中&#xff0…

【文档智能】LACE:帮你自动生成文档布局的方法浅尝

前言 往期很多文章都介绍了【文档智能】上布局识别(版式分析)的技术思路,版式分析是通过对文档版式进行布局识别,识别文档中的元素类型的过程。这次来看看一个有趣的思路,通过已有的元素类型,来生成可控的…

赠你一只金色的眼 - 富集分析和表达数据可视化

GOplot包介绍 GOplot包用于生物数据的可视化。更确切地说,该包将表达数据与功能分析的结果整合并进行可视化。但是要注意该包不能用于执行这些分析,只能把分析结果进行可视化。在所有科学领域,由于空间限制和结果所需的简洁性,切…

Agent如何帮助大模型“增强记忆”?

Agent如何帮助大模型“增强记忆”? 原创 格林 神州问学 2024年07月08日 17:50 日本 记忆反馈 >规划? 来源|神州问学 引言 去年6月份,Lilian发布了关于LLM驱动的Agent的结构和组件,其中包括规划、行动、工具还有记忆&#xff…

带有子节点的树状表的父节点拖动排序#Vue3#Sortable插件

带有子节点的树状表的父节点拖动排序#Vue3#Sortable插件 使用Sortable插件这里要保证获取到的是父节点的下标&#xff0c;属性newDraggableIndex获取到的就是只有父节点的下标。设置子节点不能被拖动&#xff0c;最后在逐个调用接口进行数据库中顺序的更新。 <template>…

4.10-7.9

4.14 System.getCurrentMills(); fis.read()和fis.read(bytes)。一个是一次读取一个字节&#xff0c;一个是一次读取一个字节数组个字节。返回值一个是读取到的字符的ascii表示&#xff08;数字&#xff09;,一个是返回读取到的字节数。读取到最后都是返回-1。read(bytes)会把…

【Python】已解决:SyntaxError: invalid character in identifier

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;SyntaxError: invalid character in identifier 一、分析问题背景 在Python编程中&#xff0c;SyntaxError: invalid character in identifier是一个常见的编译…

面经-计算机网络-数据结构-堆

1.什么是堆 堆是一种满足以下条件的树&#xff1a; 堆中的每一个节点值都大于等于&#xff08;或小于等于&#xff09;子树中所有节点的值。或者说&#xff0c;任意一个节点的值都大于等于&#xff08;或小于等于&#xff09;所有子节点的值。 2.堆的用途 当我们只关心所有数…

tk Text文本框赋值,清空

import tkinter as tk# 创建主窗口 root tk.Tk() root.title("文本框内容赋值示例")# 创建一个Text小部件 text_area tk.Text(root, height10, width50) text_area.pack()# 将内容赋值给Text小部件 text_area.insert(tk.END, "这是文本框中的内容。\n")#…

android CameraX构建相机拍照

Android CameraX 是一个 Jetpack 支持库&#xff0c;旨在简化相机应用的开发工作。它提供了一致且易用的API接口&#xff0c;适用于大多数Android设备&#xff0c;并可向后兼容至Android 5.0&#xff08;API级别21&#xff09;。 CameraX解决了在多种设备上实现相机功能时所遇…