3、日志过滤与搜索:使用grep进行关键字过滤、多条件组合过滤、正则表达式在日志分析中的应用、时间范围过滤
日志文件动不动就几百兆,甚至几个G。你不可能一行一行去看。这时候,grep就是你的瑞士军刀。我个人习惯,打开终端第一件事就是敲grep,它帮我节省了至少80%的排查时间。
3.1 基础关键字过滤:从大海捞针到精准定位
最简单的用法,就是直接搜一个词。比如你想看所有包含“crash”的日志:
adb logcat | grep "crash"
嗯,这里要注意。如果你在Windows的CMD里跑,记得用双引号。Linux或Mac下单引号双引号都行,但为了统一,我建议都用双引号。
我在项目中遇到过一个问题:搜“error”出来一大堆,但很多是第三方库的冗余信息。怎么办?加个-i参数忽略大小写,或者用-w做整词匹配:
adb logcat | grep -iw "error"
这样就不会把“ErrorHandler”这种也匹配出来了。说白了,-w就是告诉grep:我只想要完整的单词“error”,别给我拆开。
adb logcat -s system_server | grep "crash"。先按进程过滤,再按关键字过滤,效率翻倍。
3.2 多条件组合过滤:与、或、非的灵活运用
实际工作中,很少只搜一个词。比如我想看“anr”相关的日志,但又不想看“InputDispatcher”的ANR(因为那通常是输入事件超时,不是真正的应用ANR)。这时候就需要组合过滤。
与(AND)操作: 用管道串联多个grep
adb logcat | grep "anr" | grep -v "InputDispatcher"
-v就是取反,排除掉包含“InputDispatcher”的行。我曾经排查一个系统ANR问题,就是靠这个组合过滤,把几百条日志缩减到十几条,最终定位到是某个服务持锁导致。
或(OR)操作: 用-E开启扩展正则,或者用\|
adb logcat | grep -E "anr|crash|watchdog"
这样就能同时匹配ANR、crash、watchdog三种关键字。我个人习惯用-E,因为可读性更好。
非(NOT)操作: 就是上面说的-v。可以叠加使用:
adb logcat | grep "error" | grep -v "vendor" | grep -v "debug"
你想想看,这样一层层过滤下去,最终留下的就是真正需要关注的核心日志。
3.3 正则表达式在日志分析中的应用
正则表达式,说白了就是更高级的搜索模式。grep默认支持基础正则,加上-E后支持扩展正则,功能更强。
常见场景1:匹配行首或行尾
日志的每一行通常以日期或优先级开头。比如我想找所有以“E/”开头的行(Error级别):
adb logcat | grep "^E/"
^表示行首。同理,$表示行尾。比如你想找以句号结尾的行,虽然不常用,但知道总没坏处。
常见场景2:匹配任意字符
点号.匹配任意单个字符。比如我想找“pid 1234”或“pid 5678”这种模式:
adb logcat | grep -E "pid [0-9]+"
[0-9]+表示匹配一个或多个数字。我在项目中遇到过需要提取所有进程ID的场景,用这个正则配合-o参数(只输出匹配部分),就能快速拿到所有PID列表。
常见场景3:匹配时间戳
Android日志的时间戳格式通常是“01-01 12:00:00.123”。如果你想找某个特定秒内的日志:
adb logcat | grep -E "01-01 12:0[0-5]:"
这表示匹配12:00到12:05之间的所有日志。嗯,这里要注意,正则写得太复杂容易出错,我建议先写个简单的测试一下,确认没问题再正式用。
3.4 时间范围过滤:只关注关键时间窗口
很多时候,问题只发生在某个时间点前后。比如用户反馈“下午3点手机重启了”,你不需要看全天的日志。
方法1:用grep配合时间字符串
如果日志文件已经保存到本地,可以直接用grep匹配时间:
grep "15:00" bugreport.txt
但这只能精确到分钟。如果想看15:00到15:05之间的日志,可以用正则:
grep -E "15:0[0-5]:" bugreport.txt
方法2:用sed截取时间范围
我个人更推荐用sed,因为它可以按行号或模式截取。比如我想看15:00:00到15:05:00之间的日志:
sed -n '/15:00:00/,/15:05:00/p' bugreport.txt
这个命令的意思是:从匹配“15:00:00”的行开始打印,直到匹配“15:05:00”的行结束。注意,如果日志里没有精确的“15:05:00”,它会一直打印到文件末尾。所以最好选一个肯定存在的日志行作为结束标记。
方法3:实时过滤logcat的时间
如果你在实时抓取logcat,可以用-T参数指定起始时间:
adb logcat -T "01-01 15:00:00.000"
这样只会显示该时间点之后的日志。我经常在复现问题前先执行这个命令,等用户复现完,日志就已经被精准截取了。
3.5 综合实战:一个完整的日志过滤流程
假设你要排查一个“应用闪退”的问题。用户说“大概在下午2点半左右”。你的操作流程应该是:
- 先按时间截取:
sed -n '/14:29:00/,/14:31:00/p' bugreport.txt > window.txt - 再按关键字过滤:
grep -E "crash|fatal|exception|ANR" window.txt > crash_log.txt - 排除干扰项:
grep -v "vendor" crash_log.txt > final_log.txt - 查看上下文:
grep -C 5 "com.example.app" final_log.txt(显示匹配行前后各5行)
这样下来,原本几万行的日志,最终可能只剩下几十行。你想想看,是不是效率高了很多?