一、问题背景:为什么我们要“重新造日志体系”?

在实际项目中,我们经常会遇到这样的问题:

  • 问题难复现:客户现场偶发问题,回传日志不完整

  • Kernel / Logcat / 网络日志割裂:信息分散,无法关联分析

  • 日志不可控

    • 一直开 → 占空间、影响性能
    • 关了 → 出问题没数据
  • tcpdump 需要人工介入,现场操作成本高

结论

不是“日志不够多”,而是日志体系缺乏工程化设计

于是需求就变成了一句话:

在不影响系统稳定性的前提下,构建一套可开关、可轮转、可统一管理的系统级日志采集方案。


二、需求拆解:工程师是如何“拆问题”的?

我习惯把需求拆成 4 个维度

1️⃣ 日志类型维度
类型 目的
logcat Framework / App 问题
kernel 驱动 / 底层异常
tcpdump 网络问题定位
2️⃣ 生命周期维度
  • 开机是否自动准备环境?
  • 是否支持 运行期动态开关
  • 是否随 reboot 清理?
3️⃣ 资源控制维度
  • 单文件大小限制
  • 文件数量限制
  • tmpfs / data 分层使用
4️⃣ 可运维维度
  • Property 控制
  • 无需 adb 介入
  • 出厂默认关闭,问题时开启。(正常大厂做法userdebug开启,release版本关闭)

三、整体架构设计:不是脚本,而是“系统能力”

🧱 架构总览

┌──────────────┐
│ Android init │
└──────┬───────┘
       │ property trigger
┌──────▼────────────────────────┐
│ logcatd.rc                     │
│                                │
│ ├─ logcatlog.sh   (logcat)     │
│ ├─ kernel.sh      (dmesg -w)   │
│ └─ tcpdump.sh     (pcap)       │
└──────┬────────────────────────┘
       │
┌──────▼──────────┐
│ /data/log/tmp   │  ← tmpfs
│  logcat / kernel│
│  tcpdump pcap   │
└─────────────────┘
🎯 关键设计决策
决策 原因
使用 init.rc + property 系统级、稳定、无需 daemon 常驻
使用 shell 脚本 易维护、快速定制
tmpfs 防止 flash 写爆
oneshot service + while 可控、避免 init 重启风暴

四、技术原理拆解(核心干货)

1️⃣ 为什么不用原生 logcatd?
  • logcatd:

    • 强耦合 logd
    • 配置复杂
    • 不适合动态 TAG / 网络日志

结论
👉 logcat 是工具,logcatd 是系统组件,不要滥用


2️⃣ kernel 日志为什么用 dmesg -w

代码解读

复制代码

dmesg -w >> kernel.log

优势:

  • 实时
  • 不依赖 logd
  • 崩溃前最后信息也能抓到

配合:

  • 文件大小监控
  • kill + 轮转
  • property 动态关闭

3️⃣ tcpdump 为什么用 init service?

代码解读

复制代码

on property:persist.sys.emdoor.tcpdump=1 start tcpdump_all

好处:

  • 避免后台常驻
  • 权限天然是 root
  • 行为可审计(property)

这是系统工程思维,而不是运维脚本思维。


4️⃣ 为什么要“自己写轮转”?

原因很现实:

  • busybox logrotate 不一定存在
  • Android shell 功能受限
  • 要可控、可定制

所以用最原始、最可靠的方式:

bash

代码解读

复制代码

stat -c %s mv log log.1

五、编码层面的工程经验总结(非常重要)

✅ 1. init service 一定要 oneshot + while

❌ 错误示范:

bash

代码解读

复制代码

service xxx /system/bin/xxx.sh

一旦脚本退出 → init 无限重启

✅ 正确方式:

bash

代码解读

复制代码

service xxx /system/bin/xxx.sh oneshot

✅ 2. 永远用 property 控制行为,不用 kill -9
init

代码解读

复制代码

ENABLE=$(getprop persist.logcat.enable)

  • 可远程控制
  • 可持久化
  • 可追溯
✅ 3. tmpfs 是日志工程的“护城河”

bash

代码解读

复制代码

mount tmpfs tmpfs /data/log/tmp

好处:

  • 不伤 flash
  • 重启自动清空
  • 适合问题分析日志
✅ 4. Android.bp 用 prebuilt_binary 很关键

css

代码解读

复制代码

cc_prebuilt_binary { name: "logcatlog.sh", }

  • 不编译
  • 不引入 toolchain 问题
  • 升级风险极低

六、从“写功能”到“做系统”的思维跃迁

很多工程师会问:

“这不就是几个 shell 脚本吗?”

但真正的差别在于:

初级思维 高级工程思维
能不能跑 能不能长期稳定跑
写脚本 构建系统能力
临时抓日志 可运维、可交付
解决一次问题 降低 N 次问题成本

七、结语:日志不是辅助功能,而是系统的“黑匣子”

当系统复杂到一定程度:

日志能力 = 系统可维护性

转载请注明出处https://blog.csdn.net/qq_15950325/article/details/157326953?sharetype=blogdetail&sharerId=157326953&sharerefer=PC&sharesource=qq_15950325&spm=1011.2480.3001.8118,谢谢合作!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐