系列目录:第一篇:异常机制全景图 | 第二篇:Kernel Panic 与系统重启 | 第三篇:Tombstone 机制 | 第四篇:System Server Watchdog | 第五篇:System Server 崩溃 | 第六篇:ANR 机制 | 第七篇:Java 层崩溃 | 第八篇:Trace 机制 | 第九篇:日志系统 | 第十篇:实战方法论
一、日志系统:异常定位的"数据源"
你可能遇到过这些场景:
- 异常发生后 logcat 缓冲区已被覆盖,找不到关键日志
- 不知道
tombstone、dropbox、traces.txt分别存在哪里 - bugreport 文件巨大(10-50MB),不知道从哪个 Section 开始看
- 重启后内核日志丢失,无法分析 Kernel Panic
前 8 篇文章介绍了各种异常机制,它们产生的日志最终都汇集到 Android 的日志系统中。理解日志系统的架构,才能做到"异常发生后,知道去哪里找什么日志"。
Android 日志体系总览
┌───────────────────────────────────────────────┐ │ 日志生产者 │ │ ├─ 内核 (printk) → dmesg / pstore │ │ ├─ Native 进程 (ALOGx 宏) │ │ ├─ Java 进程 (Log.x / Slog.x) │ │ └─ debuggerd (tombstone) │ ├───────────────────────────────────────────────┤ │ 日志传输与缓冲 │ │ ├─ logd daemon (用户态日志守护进程) │ │ ├─ /dev/socket/logd (socket 通信) │ │ └─ 四种缓冲区 (main/system/crash/kernel) │ ├───────────────────────────────────────────────┤ │ 日志持久化 │ │ ├─ DropBoxManagerService (/data/system/dropbox/) │ │ ├─ tombstone (/data/tombstones/) │ │ ├─ ANR traces (/data/anr/) │ │ └─ pstore (内核 panic 日志) │ ├───────────────────────────────────────────────┤ │ 日志消费工具 │ │ ├─ logcat 命令行 │ │ ├─ dumpsys dropbox │ │ ├─ bugreport / bugreportz │ │ └─ bugreport 可视化工具(ChkBugReport 等) │ └───────────────────────────────────────────────┘二、logd 守护进程
2.1 logd 是什么
logd是 Android 的用户态日志守护进程,源码位于system/core/logd/。在 AOSP 7 中,所有Log.x()调用最终都通过logd写入日志缓冲区。
App/System 进程 │ ├─ Log.i(TAG, "message") ├─ Slog.i(TAG, "message") ← System Server 使用 └─ ALOGI("message") ← Native 进程使用 │ ▼ liblog.so (log write 接口) │ ▼ /dev/socket/logd (Unix Domain Socket) │ ▼ logd daemon ├─ LogBuffer (环形缓冲区,内存中) │ ├─ main (默认 256KB) │ ├─ system (默认 256KB) │ ├─ crash (默认 256KB) │ └─ kernel (默认 256KB) │ ├─ LogReader (响应 logcat 读取请求) └─ CommandListener (响应 clear 等命令)2.2 四种日志缓冲区
| 缓冲区 | 用途 | 典型 TAG | 读取方式 |
|---|---|---|---|
| main | App 日志(默认Log.i()写入) | 自定义 TAG | logcat -b main |
| system | 系统服务日志(Slog.i()写入) | ActivityManager、WindowManager | logcat -b system |
| crash | 崩溃相关日志 | AndroidRuntime等 | logcat -b crash |
| kernel | 内核日志 | kernel | logcat -b kernel或dmesg |
2.3 logcat 命令详解
# 基础用法adb logcat# 默认读取 main + system 缓冲区adb logcat-ball# 读取所有缓冲区adb logcat-bmain-bsystem# 读取指定缓冲区# 过滤adb logcat-sActivityManager# 只显示指定 TAGadb logcat *:W# 只显示 Warning 及以上级别adb logcat ActivityManager:I *:S# AMS 的 Info 以上,其他静默# 格式控制adb logcat-vtime# 显示时间戳adb logcat-vthreadtime# 显示时间 + 线程信息adb logcat-vbrief# 简洁格式adb logcat-vlong# 详细格式(含 PID/TID/TAG/Priority)# 输出控制adb logcat-d# dump 当前缓冲区后退出adb logcat-c# 清空缓冲区adb logcat-f/sdcard/log.txt# 输出到文件adb logcat-r1024-n5# 自动切割(每文件1MB,保留5个)# 过滤指定进程adb logcat--pid=1234# 只看指定 PID2.4 日志级别
| 级别 | 缩写 | 含义 | 使用场景 |
|---|---|---|---|
| Verbose | V | 详细信息 | 开发和调试用,不用于生产 |
| Debug | D | 调试信息 | 调试阶段的临时日志 |
| Info | I | 一般信息 | 正常流程的标记 |
| Warning | W | 警告 | 异常但可恢复的情况 |
| Error | E | 错误 | 功能异常,需要关注 |
| Fatal | F | 致命错误 | 系统级别的严重问题 |
Log.v(TAG,"verbose");// VERBOSELog.d(TAG,"debug");// DEBUGLog.i(TAG,"info");// INFOLog.w(TAG,"warning");// WARNLog.e(TAG,"error");// ERRORLog.wtf(TAG,"what a terrible failure");// ASSERT (FATAL)三、内核日志
3.1 dmesg
# 查看当前内核日志环形缓冲区adb shelldmesg# 持续监控内核日志adb shellcat/proc/kmsg# 清空内核日志adb shelldmesg-c3.2 last_kmsg(重启前最后的内核日志)
# 查看上次重启前的内核日志adb shellcat/proc/last_kmsg# 高通平台从 pstore 读取adb shellcat/sys/fs/pstore/console-ramoops3.3 dmesg vs logcat -b kernel 的区别
| 特性 | dmesg | logcat -b kernel |
|---|---|---|
| 直接来源 | 内核printk环形缓冲区 | logd 的 kernel buffer |
| 是否持久化 | 重启消失 | 重启消失 |
| 读取方式 | 直接读/dev/kmsg | 通过 logd socket |
| 包含内容 | 所有printk输出 | logd 初始时从/proc/kmsg读取的快照 |
四、DropBoxManagerService
4.1 什么是 DropBox?
DropBoxManagerService是 Android 的"异常日志收件箱",负责将各类系统异常(crash、ANR、watchdog、tombstone 等)持久化存储到磁盘。
源码路径:frameworks/base/services/core/java/com/android/server/DropBoxManagerService.java
publicclassDropBoxManagerServiceextendsIDropBoxManagerService.Stub{// ...// 存储路径:/data/system/dropbox/// 每个条目是一个文件,文件名格式:tag@timestamp.txt// ...}关键设计:DropBox 条目以文件形式持久化存储,每个条目有独立的 tag 和时间戳,不会因 logcat 缓冲区溢出而丢失。
4.2 DropBox 条目类型速查
adb shell dumpsys dropbox| Tag | 对应异常 | 包含内容 |
|---|---|---|
SYSTEM_BOOT | 系统启动 | 启动时间、上次重启原因 |
system_server_crash | System Server 崩溃 | Java 异常堆栈、进程信息 |
system_server_watchdog | System Server Watchdog | 各线程堆栈、锁信息 |
SYSTEM_TOMBSTONE | 系统进程 Native 崩溃 | 完整 tombstone 文本 |
data_app_crash | App 崩溃 | 异常类型、消息、堆栈 |
data_app_anr | App ANR | CPU 使用率、线程堆栈 |
system_app_crash | 系统 App 崩溃 | 同上(系统 App 用) |
system_app_anr | 系统 App ANR | 同上(系统 App 用) |
BATTERY_DISCHARGE_INFO | 电池放电信息 | 低电量关机时记录 |
4.3 查看 DropBox 内容
# 列出所有条目adb shell dumpsys dropbox# 查看指定条目内容adb shell dumpsys dropbox data_app_crash--print# 查看最近的条目adb shell dumpsys dropbox|head-100# 导出所有 dropbox 文件adb pull /data/system/dropbox/ dropbox_dump/五、bugreport
5.1 bugreport 是什么
bugreport是 Android 最全面的诊断信息收集命令,一键收集系统运行的所有状态信息。它相当于同时执行了以下所有操作:
logcat-ball-d# 所有日志缓冲区dmesg# 内核日志dumpsys# 所有系统服务的当前状态/data/anr/traces.txt# ANR 线程堆栈/data/tombstones/# Native 崩溃墓碑/proc/last_kmsg# 上次重启的内核日志/proc/meminfo# 内存使用情况/proc/cpuinfo# CPU 信息...(还有很多)5.2 生成 bugreport
# 方法1:传统方式(文本格式,较大)adb bugreport>bugreport.txt# 方法2:压缩格式(推荐)adb bugreportz# 输出:bugreport-NRD90M-2024-01-01-12-00-00.zip# 方法3:从设备上直接生成adb shell bugreportz adb pull /data/user_de/0/com.android.shell/files/bugreports/bugreport-*.zip5.3 bugreport 核心 Section 解读
bugreport 是一个巨大的文本文件(通常 10-50MB),以下是异常定位最需要关注的 Section:
DUMP OF SERVICE activity(当前 Activity 状态):
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities) Stack #0: Task id #1 TaskRecord{xxx #1 A=com.example.app U=0 sz=1} Hist #0: ActivityRecord{xxx u0 com.example.app/.MainActivity} state: RESUMEDDUMP OF SERVICE meminfo(内存状态):
Total RAM: 2,876,928 kB (status normal) Free RAM: 1,234,567 kB Used RAM: 1,642,361 kB Lost RAM: 0 kB ZRAM: 123,456 kB physical used ...DUMP OF SERVICE dropbox(最近异常):
显示最近的 DropBox 条目列表,快速找到异常记录。
KERNEL LOG (dmesg):
<4>[ 1234.567890] [BATTERY] capacity=80% voltage=4000mV ... <3>[ 1234.567900] eMMC: mmc0: timeout waiting for ...SYSTEM LOG (所有缓冲区):
主日志缓冲区 + 系统日志缓冲区。
EVENT LOG:
系统事件日志(二进制格式,解析后可读),包含:
am_anr:ANR 事件am_crash:崩溃事件am_proc_died:进程死亡am_proc_start:进程启动battery_level:电量变化screen_toggled:亮屏/灭屏
5.4 bugreport 快速定位技巧
# 搜索崩溃记录grep-n"FATAL EXCEPTION"bugreport.txt# 搜索 ANRgrep-n"ANR in"bugreport.txt# 搜索 Native 崩溃grep-n"signal 11\|signal 6\|signal 7"bugreport.txt# 查找 System Server Watchdoggrep-n"WATCHDOG"bugreport.txt# 查看重启原因grep-n"boot_reason\|reboot"bugreport.txt# 查找低内存杀死grep-n"Low Memory Killer\|kill.*adj"bugreport.txt六、日志存储路径汇总
| 路径 | 内容 | 持久化 | 重启后 |
|---|---|---|---|
/proc/kmsg | 内核日志(实时) | 否 | 消失 |
/proc/last_kmsg | 上次内核日志 | 通过 pstore | 可读 |
/sys/fs/pstore/ | pstore 持久化日志 | 是 | 保留 |
/data/anr/traces.txt | ANR 线程堆栈 | 是 | 保留 |
/data/tombstones/ | Native 崩溃墓碑 | 是 | 保留 |
/data/system/dropbox/ | DropBox 异常日志 | 是 | 保留 |
/dev/socket/logd | logd 缓冲区 | 否(内存) | 消失 |
七、日志抓取策略
7.1 在线收集(设备正常运行)
#!/bin/bash# 完整收集脚本TIMESTAMP=$(date+%Y%m%d_%H%M%S)DIR="bugreport_${TIMESTAMP}"mkdir-p$DIRecho"1/6 收集 bugreport..."adb bugreportz adb pull /data/user_de/0/com.android.shell/files/bugreports/bugreport-*.zip$DIR/echo"2/6 收集 logcat..."adb logcat-ball-d>$DIR/logcat_all.txtecho"3/6 收集 dmesg..."adb shelldmesg>$DIR/dmesg.txtecho"4/6 收集 ANR traces..."adb pull /data/anr/traces.txt$DIR/2>/dev/nullecho"5/6 收集 tombstone..."adb shellls/data/tombstones/|whilereadf;doadb pull /data/tombstones/$f$DIR/doneecho"6/6 收集 dropbox..."adb shell dumpsys dropbox>$DIR/dropbox.txtecho"收集完成:$DIR"7.2 离线收集(重启后)
优先级顺序: 1. /sys/fs/pstore/console-ramoops → 内核 panic 现场 2. /proc/last_kmsg → 上次内核日志 3. /data/tombstones/tombstone_* → Native 崩溃记录 4. /data/system/dropbox/ → 异常记录 5. /data/anr/traces.txt → ANR 记录八、总结
logd 是用户态日志的中心枢纽:main/system/crash/kernel 四种缓冲区各有侧重。
DropBox 是异常日志的"持久化保险箱":crash、ANR、watchdog、tombstone 都存储在此,不因 logcat 缓冲区溢出而丢失。
bugreport 是一键收集全系统状态的"瑞士军刀":集成了 logcat、dmesg、dumpsys 等所有诊断信息。
日志存储有内存和磁盘两层:logcat 缓冲区在内存(重启消失),DropBox/tombstone 在磁盘(重启保留)。
掌握日志路径映射 = 掌握问题定位的第一步:什么问题对应什么路径,是高效排障的基础。
下一篇(系列终篇)将用真实案例串联前 9 篇的所有知识,形成完整的排障方法论。
本文基于 AOSP 7(Android Nougat)源码编写。