3. bugreport 工具介绍

说实话,bugreport 是我日常排查问题用到最频繁的命令之一。你想想看,当测试同学扔过来一个「App 闪退了」或者「系统卡死了」,你第一反应是什么?我反正会先要一份 bugreport。它能把我当时不在现场的设备状态,原封不动地拉到我面前。

这一章咱们就掰开揉碎了聊聊:怎么生成 bugreport、怎么导出、以及拿到手之后那一大坨文件到底怎么看。

核心概念:bugreport = 系统状态快照 + 日志归档 + 诊断数据包。它不是某个单一日志文件,而是一个结构化的数据集合。

bugreport 生成与结构解析 adb bugreport 命令 开发者选项 → 生成报告 Key chord 组合键 系统后台收集:dumpsys + logcat + dumpstate + 各种子系统数据 输出产物:bugreport-<日期>.zip 或 .txt bugreport-xxx/ 主要文件:bugreport.txt + 日志 + dump 子目录:FS, logs, dumpstate dumpsys 输出 (内存/进程/服务) logcat 日志 (系统/应用/内核) dumpstate 报告 (异常栈/线程信息) 文件系统快照 (proc/下关键节点) ✅ bugreport 不是单一日志,而是 Android 系统在某一时刻的「全景诊断快照」

3.1 什么是 bugreport?

bugreport 是 Android 系统内置的诊断数据收集工具。说白了,它就是把设备当前的内存状态、进程列表、日志缓冲区、系统服务信息、网络状态、电池数据、文件系统关键节点……一股脑打包出来。

我个人习惯把 bugreport 理解成「设备的飞行黑匣子」。你不需要复现问题,只要在问题发生后的第一时间抓取,里面大概率已经记录了关键线索。

维度 说明 典型数据量
系统信息 构建版本、内核版本、启动时间、运行时长 约 20-50 KB
进程状态 所有进程的 CPU/内存占用、线程信息 约 200-500 KB
系统服务 ActivityManager、WindowManager、PackageManager 等状态 约 1-3 MB
日志缓冲区 main、system、events、crash、kernel 等 log 约 2-8 MB
异常信息 ANR traces、Java 堆栈、Native 堆栈 约 100-500 KB

我的经验:曾经遇到一个「Wi-Fi 连不上」的问题,测试同学复现了 3 天都没抓到规律。我让他每次连不上就立刻抓一份 bugreport,第 2 份就发现是 wpa_supplicant 进程在某个特定场景下 crash 了。没有 bugreport,这种偶发问题真的很难定位。

3.2 生成 bugreport:三种常用方式

生成 bugreport 的方式就那么几种,我按推荐度排个序:

方式一:adb 命令(最推荐)

# 生成完整 bugreport(zip 包)
adb bugreport

# 指定输出路径
adb bugreport ./my_bugreport.zip

执行后设备会开始收集数据,大概等 30 秒到 2 分钟(取决于系统负载),然后在当前目录生成一个类似 bugreport-2025-01-15-14-30-00.zip 的文件。

注意:adb bugreport 在 Android 7.0+ 上默认输出 zip 包,包含完整结构。如果你在用 Android 6.0 及以下的设备,输出的是纯文本文件,内容是一样的,只是没有目录结构。

方式二:设备端手动生成

进入「开发者选项」→ 「Bug 报告」→ 「生成报告」。系统会弹出分享菜单,你可以通过邮件、网盘等方式把文件发出来。嗯,适合没有 adb 环境的测试同学。

方式三:组合键(极少用)

同时按住「音量上 + 音量下 + 电源键」约 3 秒,设备震动后开始生成。说实话,这个方式容易误触,我一般不推荐。

对比总结:adb 方式最可控,可以指定输出路径和文件名;设备端生成适合外场测试;组合键只适合紧急场景。

3.3 导出 bugreport:两种常见场景

生成之后怎么把文件弄到电脑上?分两种情况:

场景 A:adb bugreport 直接生成在电脑上

这种情况你已经在电脑上了,文件就在当前目录,直接解压就行。

场景 B:设备端生成,需要拉取到电脑

# 查看设备上的 bugreport 文件
adb shell ls /data/bugreports/

# 拉取到电脑
adb pull /data/bugreports/bugreport-xxx.zip ./

有些厂商会把 bugreport 存在 /sdcard/bugreports/ 或者 /data/data/com.android.shell/files/bugreports/,路径稍有不同。我建议先用 adb shell find / -name "bugreport*" 2>/dev/null 扫一遍,省得一个个目录翻。

小技巧:如果你有多台设备,可以用 adb -s <serial> bugreport 指定单台设备,避免串号。

3.4 结构解析:zip 包里面到底有什么?

拿到 zip 包之后先解压,目录结构大概长这样:

bugreport-设备名-日期/
├── bugreport.txt              # 主报告文件(纯文本,超大型)
├── bugreport_info.txt         # 报告元信息(版本、时间、命令)
├── dumpstate_log.txt          # dumpstate 执行日志
├── logs/                      # 各种日志子目录
│   ├── logcat.txt             # 主 logcat 输出
│   ├── logcat.txt.gz          # 压缩版
│   ├── events.txt             # events 日志
│   ├── kernel.log             # 内核日志
│   └── radio/                 # 无线通信日志(如果设备支持)
├── FS/                        # 文件系统快照
│   ├── proc/                  # /proc 下的关键节点
│   ├── sys/                   # /sys 下的设备状态
│   └── data/                  # /data 部分关键文件
└── dumpstate/                 # 详细 dump 数据
    ├── anr/                   # ANR traces
    ├── hprof/                 # Java heap dump(如果触发)
    └── tombstone/             # Native crash tombstone

我拿到 bugreport 后的「三板斧」是这样的:

  1. 先看 bugreport.txt 的前 200 行——确认设备基本信息、运行时长、构建版本,先判断是不是已知问题。
  2. 搜 "CRASH" 和 "ANR"——用 grep -in "crash\|anr" bugreport.txt 快速定位异常。
  3. 看 logcat.txt 里目标进程的最后 500 行——确认崩溃前的操作序列。

核心思路:bugreport 数据量大,不要从头到尾读。带着问题去找线索,效率最高。

为什么会强调这个顺序?我之前有个同事,拿到 bugreport 直接双击打开,从第 1 行开始往下翻,翻了半小时还在看 CPU 频率表……你想想看,那里面光 dumpsys 的输出就几千行,这么看法太低效了。

说到 dumpsys,我再提一嘴:bugreport 里的 dumpsys 输出跟单独执行 adb shell dumpsys 是一样的,但它是一个「时间点快照」。我记得有个案例,某 App 在后台被频繁 kill,我从 bugreport 里的 dumpsys procstats 和 dumpsys meminfo 直接看到系统在持续低压杀进程,定位到是某个三方服务的内存泄漏。没有 bugreport 的全局视角,这种跨进程的问题很难串联起来。

3.5 快速使用 checklist

步骤 操作 预期产出
1 连设备,执行 adb bugreport zip 包(30秒-2分钟)
2 解压 zip,确认目录结构完整 bugreport.txt + logs/ + FS/
3 用文本编辑器打开 bugreport.txt 查看设备基本信息
4 搜索 "CRASH" / "ANR" / "FATAL" 定位异常入口
5 查看 logs/logcat.txt 中对应进程的日志 获取详细异常上下文

避坑指南:我曾经在一个项目里连续抓了 5 份 bugreport 都发现 logcat 是空的,查了半天才发现是测试机开启了「日志大小限制 = 关闭」,导致 logd 没启动。生成 bugreport 之前,最好先确认 adb shell logcat -c 之后能正常输出日志。否则你抓回来的报告,logcat 部分就是一片空白。