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 file
                    context->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 file
                    context->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));
}

参考

[ 1 ] Android物语:logcat
[ 2 ] android调试——logcat详解
[ 3 ] 玩转Android10源码开发定制(12)内核篇之logcat输出内核日志

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容