4、日志采集工具:ADB日志抓取、串口日志捕获、远程日志收集方案

做智能音箱的故障诊断,说白了就是跟日志打交道。日志拿不到,或者拿不全,后面所有分析都是瞎猜。我这些年经手过的项目,从早期的Linux小盒子到现在的Android智能音箱,日志采集这块踩过的坑真不少。今天就把三种最常用的方案掰开揉碎讲清楚。

4.1 ADB日志抓取:Android音箱的标配

现在市面上绝大多数智能音箱跑的都是Android系统。ADB(Android Debug Bridge)就是咱们最趁手的工具。我个人习惯,拿到一台新音箱,第一件事就是连上ADB试试水。

4.1.1 基础抓取命令

先说说最常用的几个命令。你想想看,音箱出问题了,第一反应肯定是看系统日志。

# 抓取所有日志,输出到文件
adb logcat -v threadtime > bugreport.log

# 按优先级过滤:只显示Error及以上级别
adb logcat *:E

# 按标签过滤:只看WiFi相关的日志
adb logcat -s WifiManager

# 清空缓冲区,重新开始抓取
adb logcat -c

嗯,这里要注意一个细节。很多新手上来就adb logcat,结果日志刷得飞快,根本来不及看。我建议加上-v threadtime参数,这样每条日志都带时间戳和线程ID,排查问题时能精确到毫秒级。

4.1.2 抓取特定进程的日志

有一次我在项目现场排查问题,音箱的语音唤醒功能时好时坏。系统日志刷得眼花缭乱,根本找不到关键信息。后来我用了按进程ID过滤的方法,一下子就锁定了问题。

# 先找到目标进程的PID
adb shell ps | grep voice

# 假设PID是1234,只抓这个进程的日志
adb logcat --pid=1234 -v threadtime

这样做的好处很明显——排除干扰,直击要害。我建议你在调试特定功能时,优先用这个方法。

4.1.3 抓取内核日志

有些底层问题,比如驱动崩溃、内存异常,用户空间的日志根本看不到。这时候就得看内核日志了。

# 抓取内核日志
adb shell dmesg > kernel.log

# 实时监控内核日志
adb shell dmesg -w

我曾经遇到过一个音箱频繁重启的问题,应用层日志一切正常,但dmesg里清清楚楚地写着Out of memory: killed process。说白了,就是内存泄漏把系统搞崩了。

我的小技巧: 抓日志时,最好同时抓应用日志和内核日志。两个对照着看,很多问题就一目了然了。

4.2 串口日志捕获:底层调试的救命稻草

ADB虽然方便,但有个致命弱点——系统必须能正常启动。如果音箱卡在开机阶段,或者内核直接panic了,ADB根本连不上。这时候,串口就是最后的希望。

4.2.1 硬件连接

串口调试需要硬件支持。大多数智能音箱的主板上都预留了串口焊盘,一般是3.3V电平的UART接口。你需要准备一个USB转串口工具,比如FT232或者CH340。

接线方式很简单:

  • GND:地线,必须接
  • TX:音箱发送,接工具的RX
  • RX:音箱接收,接工具的TX
  • VCC:一般不用接,串口是独立供电的
警告: 千万别接反TX和RX!我见过有人接反了,折腾半天以为设备坏了。另外,确认好电平标准,3.3V的设备别接到5V上,会烧芯片的。

4.2.2 串口工具配置

Windows上我习惯用PuTTY或者SecureCRT,Linux下直接用screen或者minicom。波特率一般是115200,但也有用921600的,具体看芯片手册。

# Linux下使用screen连接串口
sudo screen /dev/ttyUSB0 115200

# 退出screen:Ctrl+A,然后按K

嗯,这里有个坑。有些USB转串口工具在Linux下需要装驱动,否则识别不出来。我建议你提前在开发机上装好ch341或者ftdi_sio驱动。

4.2.3 抓取启动日志

串口最大的价值,就是能看到从uboot开始的完整启动过程。我遇到过一台音箱,开机后屏幕一直黑着。ADB连不上,串口一接上去,日志显示DRAM initialization failed——内存初始化失败,硬件问题。

# 将串口日志保存到文件(Linux)
sudo cat /dev/ttyUSB0 > serial_boot.log

# 或者用screen自带的日志功能
screen -L -Logfile serial.log /dev/ttyUSB0 115200

我个人习惯,每次拿到新设备,都会用串口抓一次完整的启动日志保存下来。这样以后出问题了,可以对比着看,哪里变了就一目了然。

4.3 远程日志收集方案:量产后的运维利器

前面两种方法都要求设备在本地,能物理接触。但音箱一旦量产发货到用户家里,出了问题怎么办?总不能让人家寄回来吧。这时候就需要远程日志收集方案了。

4.3.1 日志上传到云端

最常用的方案,是在音箱固件里集成一个日志上传模块。当检测到异常时,自动打包日志上传到云端服务器。

# 伪代码示例:日志上传模块
def upload_logs():
    # 打包日志文件
    log_files = ["/data/logs/system.log", 
                 "/data/logs/crash.log",
                 "/data/logs/network.log"]
    
    # 创建tar包
    tar_cmd = "tar -czf /tmp/logs.tar.gz " + " ".join(log_files)
    os.system(tar_cmd)
    
    # 上传到云端
    upload_url = "https://log-collector.example.com/upload"
    upload_file("/tmp/logs.tar.gz", upload_url)

这里要注意几个问题:

  • 日志大小控制:用户家的网络可能很慢,日志包不能太大。我一般限制在5MB以内,超过就截断。
  • 上传时机:别在音箱播放音乐时上传,会影响用户体验。我建议在待机或者深夜自动上传。
  • 隐私保护:日志里不能包含用户语音数据或者WiFi密码。这个一定要做过滤,否则会出大问题。

4.3.2 远程ADB方案

有些高端音箱支持远程ADB调试,说白了就是通过网络转发ADB端口。这样工程师坐在办公室,就能像操作本地设备一样调试远程音箱。

# 在音箱上启动ADB网络服务
adb tcpip 5555

# 从远程电脑连接(假设音箱IP是192.168.1.100)
adb connect 192.168.1.100:5555

# 连接成功后,所有ADB命令照常使用
adb logcat -v threadtime
重要提醒: 远程ADB一定要做好安全防护。我建议只在内部测试网络中使用,或者通过VPN连接。直接暴露在公网上,等于给黑客开了后门。

4.3.3 日志轮转策略

日志不能无限增长,否则会把存储空间撑爆。我建议在固件里实现日志轮转机制。

日志类型 保留数量 单个文件大小 说明
系统日志 5个 2MB 循环覆盖,保留最近5份
崩溃日志 10个 1MB 每次崩溃单独保存
网络日志 3个 500KB 只保留最近3天的
用户操作日志 7个 1MB 保留一周的操作记录

我曾经遇到过一个问题,日志轮转没做好,音箱用了一个月后存储空间满了,导致OTA升级失败。从那以后,我每次做固件都会仔细检查日志轮转策略。

4.4 三种方案的选型建议

说了这么多,到底该用哪种方案?我根据实际经验总结一下:

  • 开发调试阶段:优先用ADB,方便快捷。遇到底层问题,上串口。
  • 硬件测试阶段:串口必备,能看到完整的启动过程。
  • 小批量试产:ADB+串口结合使用,同时开始搭建远程日志方案。
  • 量产阶段:远程日志收集是标配,ADB和串口作为备用方案。
我的建议: 别等到出问题了才想起搭日志系统。在产品设计阶段,就把日志采集方案考虑进去。硬件上预留串口焊盘,软件上集成远程日志模块。这样后面出了问题,你手里才有「弹药」可用。

嗯,日志采集就讲到这里。说白了,ADB是日常主力,串口是最后防线,远程方案是量产保障。三种方案各有各的用处,关键是要根据实际情况灵活选用。下一章我们聊聊日志分析的具体方法,到时候会用到今天采集的这些日志数据。