8、日志分析(Logcat):adb logcat 基础用法、日志级别(V/D/I/W/E)、过滤日志、保存日志到文件

做 Android 开发,说白了就是跟 Bug 打交道。而 Logcat,就是我们手里最趁手的「探针」。我见过太多新手,遇到问题就两眼一抹黑,其实只要学会看日志,大部分问题都能自己搞定。

这一章,我就带你彻底搞懂 Logcat。从最基础的命令,到高级的过滤技巧,再到实战中的避坑指南,咱们一步到位。

8.1 什么是 Logcat?

Logcat 是 Android 系统提供的一个日志输出系统。你的 App 里写的 Log.d()Log.e(),系统底层的各种运行信息,都会通过它吐出来。

你可以把它想象成飞机的「黑匣子」—— 飞机出事了,第一件事就是找黑匣子。App 出问题了,第一件事就是看 Logcat。

核心命令:
adb logcat

就这么简单。在终端里敲下这行命令,日志就会像瀑布一样刷刷地往下滚。

8.2 日志级别(V/D/I/W/E)

日志是有「等级」的。就像新闻一样,有「一般消息」、「重要通知」、「紧急警报」。Android 定义了五个级别,从低到高分别是:

级别 缩写 含义 使用场景
Verbose V 啰嗦模式 开发调试时随便打,发布版本要删掉
Debug D 调试信息 排查问题时临时加的日志
Info I 普通信息 记录关键流程,比如「登录成功」
Warning W 警告 可能有问题,但还没崩
Error E 错误 出异常了,赶紧看!

我个人习惯,开发时用 Log.d() 打调试日志,上线前统一清理。千万别把 Log.v() 留在线上版本里,那日志量能把用户手机撑爆。

小技巧:

在代码里,你可以这样打日志:

Log.d("MainActivity", "用户点击了登录按钮");
Log.e("MainActivity", "登录失败,错误码:" + errorCode);

第一个参数是「标签」(Tag),第二个是「内容」。标签用来区分日志来自哪个类,内容就是你想看的信息。

8.3 过滤日志:只抓你想要的

直接跑 adb logcat,你会看到海量信息。系统日志、其他 App 的日志、内核日志…… 全混在一起。这时候就需要过滤了。

8.3.1 按标签过滤

这是最常用的方式。比如我只想看 MainActivity 的日志:

adb logcat -s MainActivity

或者同时看多个标签:

adb logcat -s MainActivity:V NetworkUtils:D

这里的 :V:D 表示日志级别。意思是「只看 MainActivity 的 Verbose 及以上级别,以及 NetworkUtils 的 Debug 及以上级别」。

8.3.2 按级别过滤

我只想看 Error 级别的日志,其他一概不管:

adb logcat *:E

这个命令的意思是「所有标签(*),只看 Error 及以上级别」。嗯,这里要注意,*:E 会显示所有 App 的 Error 日志,包括系统本身的。如果你只想看自己 App 的,最好结合标签过滤。

8.3.3 用 grep 做高级过滤

有时候标签不够用,我想搜包含「login」关键字的日志:

adb logcat | grep "login"

这是 Linux 的管道操作。把 Logcat 的输出,交给 grep 命令做文本搜索。我在项目中遇到过一个问题:某个接口返回了奇怪的 JSON,我就是用 grep "response" 从海量日志里捞出来的。

避坑指南:

我曾经在线上环境用 adb logcat | grep "password" 查问题,结果把用户的密码明文日志给抓出来了。后来被安全团队约谈…… 所以,永远不要在日志里打印敏感信息,比如密码、Token、身份证号。

8.4 保存日志到文件

日志一直滚屏,你根本来不及看。更常见的是把日志保存下来,慢慢分析,或者发给同事帮忙看。

8.4.1 保存到本地文件

adb logcat -d > app_log.txt

-d 参数的意思是「dump(倾倒)」,把当前缓冲区里的日志一次性倒出来,然后退出。这样你得到的是一个静态的文本文件。

如果你想持续记录,可以不加 -d

adb logcat > app_log.txt

这样日志会一直写入文件,直到你按 Ctrl + C 停止。

8.4.2 带时间戳保存

分析问题时,时间戳非常关键。比如用户说「我点了按钮后 3 秒才响应」,你就能精确看到那 3 秒里发生了什么。

adb logcat -v time > app_log_with_time.txt

-v time 表示输出格式带时间。还有其他格式,比如 -v threadtime 会显示线程 ID 和时间,适合分析多线程问题。

8.4.3 清空缓冲区再保存

有时候日志太旧了,我想从「现在」开始抓:

adb logcat -c
adb logcat > fresh_log.txt

-c 是 clear(清空)的意思。先清空缓冲区,再开始抓取,这样文件里就只有新日志了。

我的习惯:

我一般会这样组合使用:

adb logcat -c && adb logcat -v time -s MyApp:V > myapp_$(date +%Y%m%d_%H%M%S).log

这条命令做了三件事:清空旧日志、只抓 MyApp 标签的日志、带时间戳、文件名带当前时间。这样每次抓的日志都不会覆盖,而且一目了然。

8.5 知识体系总览

下面这张图,帮你把 Logcat 的核心知识点串起来:

Logcat 知识体系 adb logcat 日志级别 V/D/I/W/E 过滤日志 保存到文件 Verbose (V) Debug (D) Info (I) Warning (W) Error (E) 按标签 -s 按级别 *:E grep 搜索 组合过滤 重定向 > -d 一次性 -v time 时间戳 -c 清空缓冲区 核心:级别 + 过滤 + 保存 = 高效调试

8.6 实战:一次完整的日志分析流程

光说不练假把式。我给你模拟一个真实场景:

用户反馈,点击「登录」按钮后,App 闪退了。你该怎么查?

  1. 先清空旧日志adb logcat -c
  2. 复现问题:让用户再点一次登录按钮
  3. 抓取日志adb logcat -v time -d > crash_log.txt
  4. 分析日志:打开文件,搜索 FATAL EXCEPTIONAndroidRuntime

为什么会搜这两个关键词?因为 App 崩溃时,Android 系统会打印一条 FATAL EXCEPTION 日志,后面跟着完整的堆栈信息。你只要找到它,就能定位到是哪行代码出了问题。

我记得有一次,一个同事搞了三天没找到的 Bug,我过去一看日志,发现是 NullPointerException,空指针。原因很简单:登录接口返回的数据里,有个字段是 null,但代码直接调用了它的方法。这种问题,看日志五分钟就能定位。

总结一下:

Logcat 是 Android 调试的「眼睛」。学会用它,你就从「盲人摸象」变成了「明察秋毫」。别怕日志多,学会过滤和保存,你就能从海量信息里快速找到关键线索。


公众号:蓝海资料掘金营,微信deep3321