Android 日志系统分析(三):logcat
一、前言
logcat 作为读取日志的工具,相当于client 的角色;在前两篇文章中,关于 logcat 如何与其他部分沟通获取日志信息的流程已经介绍的比较清晰,本文不在赘述,转而归纳一下 logcat 的一些常用指令,并对其中一些做详细分析
二、命令简介
选项 | 描述 | eg |
---|---|---|
-s | 输出指定 tag 的日志,相当于过滤器表达式 '*:S' | logcat -s tag |
-f <file> | 设置logcat 内容保存的位置,默认是stdout | logcat -f sdcard/log.txt |
-r <kbytes> | 每输出 <kbytes> 时轮替日志文件,默认是16 必须配合 -f (暂不明白) | logcat -f sdcard/log.txt -r 1 |
-n <count> | 设置日志输出的最大数目, 需要 -r 参数 | 暂不明白 |
-v <format> | 设置日志消息的输出格式。详见下文 格式化输出 | logcat -v thread |
-D | 输出各个日志缓冲区之间的分隔线 | logcat -D ... |
-c | 清除(清空)所选的缓冲区并退出,默认清除 main、system 和 crash | logcat -c / -b all -c |
-d | 将日志转储到屏幕并退出 | logcat -d > log.txt |
-e <expr> | 输出正则匹配的日志消息 | logcat -e 匹配数据 -m 5 |
-m <count> | 输出 <count> 行后退出 | ...... |
-t <count> | 仅输出最新的行数,此选项包括 -d 功能 | logcat -t 5 |
-t '<time>' | 输出自指定时间以来的最新行,此选项包括 -d 功能 | logcat -t '01-26 20:52:41.820' |
-g | 获取指定日志缓冲区的大小并退出 | logcat -g |
-G | 设置日志环形缓冲区的大小,可以在结尾处添加 K 或 M | logcat -G 2M |
-b | 加载可供查看的日志缓冲区,更多可见下文 日志缓冲区 | logcat -b system |
-B | 以二进制文件形式输出日志 | ...... |
-S | 在输出中包含统计信息,以识别和定位日志垃圾信息发送者 | ...... |
--pid=<pid> | 仅输出来自给定 PID 的日志 | logcat --pid=4355 |
三、日志缓冲区
Android 日志系统为日志消息保留了多个环形缓冲区,但并非多有的日志消息都会发送到默认的环形缓冲区。这里可以采用 logcat -b 命令查看设备的其他缓冲区:
缓冲区 | 描述 | eg |
---|---|---|
radio | 输出通信系统的日志,包含无线装置/电话相关消息 | logcat -b radio |
events | 输出event模块的日志 | logcat -b events |
main | 主日志缓冲区(默认),不包含系统和崩溃日志消息 | logcat -b main |
system | 输出系统日志 | logcat -b system |
crash | 输出崩溃日志 | logcat -b crash |
all | 输出所有缓冲区日志 | logcat -b all |
default | 输出main、system、crash缓冲区日志 | logcat -b default |
如果需要查看内核空间日志信息,可采用如下几种方式查看:
1、读取 /proc/kmsg ,命令如下
adb shell cat /proc/kmsg
读取/proc/kmsg属于消费型读取,读取之后再次读取不会显示已经读取过的日志信息
2、读取 /dev/kmsg,命令如下
adb shell cat /dev/kmsg
读取/dev/kmsg会显示缓存区里面的所有日志信息。新写入的日志信息会不断累加到日志缓冲器中
3、使用 dmesg 命令读取
adb shell dmesg
dmesg命令读取一次只显示一部分日志,非阻塞执行
四、格式化输出
使用 -v 命令来修改 log 的输出格式,以显示特定的元数据字段:
格式 | 描述 | eg |
---|---|---|
brief | 显示优先级、标记以及发出消息的进程的 PID | ...... |
long | 显示所有元数据字段,并使用空白行分隔消息 | ...... |
process | 仅显示 PID | ...... |
raw | 显示不包含其他元数据字段的原始日志消息 | ...... |
tag | 仅显示优先级和标记 | ...... |
thread | 旧版格式,显示优先级、PID 以及发出消息的线程的 TID | ...... |
threadtime | (默认值)显示日期、调用时间、优先级、标记、PID 以及发出消息的线程的 TID | ...... |
time | 显示日期、调用时间、优先级、标记以及发出消息的进程的 PID | ...... |
color | 使用不同的颜色来显示每个优先级 | ...... |
descriptive | 显示日志缓冲区事件说明。此修饰符仅影响事件日志缓冲区消息,不会对其他非二进制文件缓冲区产生任何影响 | ...... |
epoch | 显示自 1970 年 1 月 1 日以来的时间(以秒为单位) | ...... |
monotonic | 显示自上次启动以来的时间(以 CPU 秒为单位) | ...... |
printable | 确保所有二进制日志记录内容都进行了转义 | ...... |
uid | 如果访问控制允许,则显示 UID 或记录的进程的 Android ID | ...... |
usec | 显示精确到微秒的时间 | ...... |
UTC | 显示 UTC 时间 | ...... |
year | 将年份添加到显示的时间 | ...... |
zone | 将本地时区添加到显示的时间 | ...... |
优先级:
选项 | 描述 | eg |
---|---|---|
V | –Verbose(最低优先级) | adb logcat *:v |
D | – Debug | adb logcat *:d |
I | – Info | adb logcat *:i |
W | – Warning | adb logcat *:w |
E | – Error | adb logcat *:e |
F | – Fatal | adb logcat *:f |
S | – Silent | adb logcat *:s |
五、logcat -f 命令详解
logcat -f 命令可以将日志消息输出到指定的文件中。这里我们需要确定的一件事是 logcat 作为客户端的角色,会将通过 liblog 获得的日志信息进行格式解析、格式化处理,而 liblog 库本身并不存在保存、解析的功能。这里来对 -f 指令做一下解析:
logcat_main.cpp # main()---> logcat.cpp # android_logcat_run_command()---> __logcat(){......case 'f':if ((tail_time == log_time::EPOCH) && !tail_lines) {tail_time = lastLogTime(optctx.optarg);}// redirect output to a filecontext->outputFileName = optctx.optarg; //注释 ①break;......setupOutputAndSchedulingPolicy() //注释 ②while (...) { //注释 ③int ret = android_logger_list_read(logger_list, &log_msg);if (context->printBinary) {printBinary(context, &log_msg);} else {processBuffer(context, dev, &log_msg);}......}
5.1 注释① :解析 -f 指令
case 'f':if ((tail_time == log_time::EPOCH) && !tail_lines) {tail_time = lastLogTime(optctx.optarg);}// redirect output to a filecontext->outputFileName = optctx.optarg; //注释 ①break;
在 _logcat() 函数中解析 -f 指令,设置日志输出文件。例如 logcat -f sdcard/log.txt ,则 context->outputFileName 赋值为 sdcard/log.txt;
5.2 注释② :设置输出路径
static void setupOutputAndSchedulingPolicy(android_logcat_context_internal* context, bool blocking) {if (!context->outputFileName) return;......// 打开文件获得 fd context->output_fd = openLogFile(context->outputFileName);if (context->output_fd < 0) {logcat_panic(context, HELP_FALSE, "couldn't open output file");return;}......
}
5.3 注释③ :写入日志
while (...) { // 调用 liblog 库中的 android_logger_list_read 函数获取日志 int ret = android_logger_list_read(logger_list, &log_msg);if (context->printBinary) { // 根据上面获取的文件 fd ,将日志消息写入文件printBinary(context, &log_msg);} else {processBuffer(context, dev, &log_msg);}
以 printBinary() 函数为例:
logcat.cpp # printBinary() :
void printBinary(android_logcat_context_internal* context, struct log_msg* buf) {size_t size = buf->len();TEMP_FAILURE_RETRY(write(context->output_fd, buf, size));
}
作者:猫咪不吃鱼
链接:https://www.jianshu.com/p/26252ee91726
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Android 日志系统分析(三):logcat相关推荐
- Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析-[Android取经之路]
摘要:本节主要来讲解Android10.0 logd.logcat读写日志源码内容 阅读本文大约需要花费20分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Andro ...
- Android日志系统分析之开篇
在android系统中, 提供了一个轻量级的日志系统.该日志系统基于在内核中实现的一个字符设备驱动 logger(misc字符设备驱动).通过该字符设备驱动,android分别提供了C/C++和Jav ...
- Android日志系统分析之日志设备驱动程序代码阅读
android日志系统中定义了设备驱动的实现代码位于kernel/common/drivers/staging/android/logger.h和kernel/common/drivers/stagi ...
- Android编译系统分析三:make完整编译android系统
这篇博客的目标是摸清楚默认编译整个android系统时代码的流程. 当我们执行make的时候,会查找当前的Makefie文件或者makefile文件并且执行,在android顶级源码目录下面,确实有个 ...
- Android 编译系统分析(三)
自Android开源以来,引起了嵌入式行业一股热潮,很多嵌入式开发者表示对Android有很强的兴趣,并下载Android源码进行编译和移植.Android源码的巨大(repo下来,大概2G)给人以A ...
- Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化-[Android取经之路]
摘要:本节主要来讲解Android10.0 日志系统的架构分析,以及logd.logcat的初始化操作 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级 ...
- Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性-[Android取经之路]
摘要:本节主要来讲解Android10.0 日志系统的logd.logcat相关指令说明.日志分类和常用日志属性 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Andro ...
- Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现-[Android取经之路]
摘要:本节主要来讲解Android10.0 selinux.kernel日志在logd中的实现,包括LogAudit.LogKlog的源码分析 阅读本文大约需要花费15分钟. 文章首发微信公众号:In ...
- Android日志[进阶篇]三-Logcat 命令行工具
Android日志[进阶篇]一-使用 Logcat 写入和查看日志 Android日志[进阶篇]二-分析堆栈轨迹(调试和外部堆栈) Android日志[进阶篇]三-Logcat命令行工具 Androi ...
最新文章
- java api中的设计模式_Java API 设计模式之策略(Strategy)
- 陈老师Linux内核内存寻址导学
- Linux基本网路配置及软件包的安装
- android 双 webview,Android webview加载页面
- 番茄日志发布1.0.3版本-增加Kafka支持
- bs架构 erp 进销存_从依赖经验到用柔性ERP,企业少走了多少弯路?
- [luogu3380][bzoj3196]【模板】二逼平衡树【树套树】
- okhttp 工具类_日语学习工具推荐,小白必备!
- 传言成真 天融信收购傲天动联
- 田间小麦病害自动诊断系统(野外复杂环境)
- jquery 动态添加,降低input表单的方法
- 全国乡镇边界及名称的下载与格式转换方法(水经注万能地图X3.1+CASS10.1.5组合拳)
- 苹果8a1660是什么版本_苹果7a1660是什么版本
- 再更新:2022 京东/淘宝双11活动一键自动完成任务脚本app来了,顺便说个事情...
- Pascal词法分析器用java实现
- 数据结构---线性表
- LaTeX的正负号写法
- 升平,景玉军.计算机虚拟技术在高职汽车维修教学中的应用研究[j].,汽车新技术教学方法探讨...
- 锚点是什么?锚点的使用
- bmi计算 python_python tkinter bmi计算
热门文章
- JavaWeb 访问JSP报错解决--org.apache.jasper.compiler.Compiler generateClass
- 一个比较好、中文说明的emacs配置文件 1
- Android 安卓动画 补间动画 - 组合(四个动画) 动画
- 在路上—Tinyfool的程序员生涯(大学篇)
- EasyExcel简单的写和多table的写
- 工控主板启动不显示的故障原因
- SGU 103 Traffic Lights
- 2020计算机考研院校推免,2020考研:热门院校推免比例超90%?他们说尝试了就不后悔!...
- 相机螺纹接口:C口和CS口
- 天翼云应用实操-天翼云资源池间通过IPSEC实现高速互通