3、日志分析工具:grep/awk/sed实战、jq处理JSON日志、Python日志解析库

日志分析这事儿,说白了就是跟文本打交道。你面对的可能是一天几个GB的纯文本,也可能是结构化的JSON。工具选对了,事半功倍;选错了,那就是在浪费时间。

我个人习惯把日志分析工具分成三类:文本三剑客(grep/awk/sed)、JSON专用工具(jq)、以及脚本级解析库(Python)。这三类工具各有各的战场,也各有各的坑。今天咱们就一个一个过。

核心观点:没有万能工具。grep适合快速过滤,awk适合结构化文本,sed适合原地修改,jq是JSON日志的救星,Python则是你最后的“核武器”。

3.1 文本三剑客:grep、awk、sed

这三个命令,是Linux运维的基本功。我见过不少新人,一上来就写Python脚本去解析日志,其实用一行awk就能搞定。你想想看,何必呢?

3.1.1 grep:最快的过滤工具

grep的核心能力就一个字:快。它不做计算,不修改内容,只负责把匹配的行捞出来。

# 查找所有包含"ERROR"的日志行
grep "ERROR" app.log

# 递归搜索整个目录
grep -r "OutOfMemoryError" /var/log/app/

# 显示匹配行的前后5行上下文
grep -C 5 "NullPointerException" app.log

# 只统计匹配次数,不输出内容
grep -c "timeout" access.log

我在项目中遇到过一个问题:某天线上服务突然变慢,日志量暴增。我直接用grep -c "ERROR"统计了每分钟的错误数,发现从10:23开始错误数直线上升。定位到时间窗口后,再配合grep -C看上下文,五分钟就找到了罪魁祸首——一个空指针异常。

小技巧:如果日志文件特别大(比如超过1GB),先用grep -l找出包含关键字的文件,再针对性地分析。别一上来就全量扫描,那是给自己找麻烦。

3.1.2 awk:结构化文本的瑞士军刀

awk比grep强在哪?它能按列处理。日志里最常见的格式就是空格或制表符分隔的字段,awk天生就是干这个的。

# 打印第1列和第3列
awk '{print $1, $3}' app.log

# 过滤第5列大于1000的行
awk '$5 > 1000 {print $0}' access.log

# 统计每个IP的访问次数
awk '{count[$1]++} END {for (ip in count) print ip, count[ip]}' access.log

# 按分隔符":"切割,取第2列
awk -F':' '{print $2}' /etc/passwd

嗯,这里要注意:awk的默认分隔符是空格,如果你的日志用逗号或竖线分隔,记得用-F指定。我曾经因为忘了这个,浪费了半小时查数据。

3.1.3 sed:流式编辑的利器

sed的强项是原地修改和正则替换。它不擅长统计,但做文本清洗是一把好手。

# 将所有"ERROR"替换为"WARN"
sed 's/ERROR/WARN/g' app.log

# 删除所有空行
sed '/^$/d' app.log

# 只打印第10到第20行
sed -n '10,20p' app.log

# 在每行开头添加时间戳
sed 's/^/[2025-01-15] /' app.log

避坑指南:sed默认不会修改原文件。如果你想直接改原文件,记得加-i参数。但千万先在副本上测试,我曾经手滑把生产环境的配置文件改坏了……嗯,那是个难忘的夜晚。

3.2 jq:JSON日志的解析神器

现在很多应用都输出JSON格式的日志。为什么?因为结构清晰,机器可读性好。但JSON日志用grep去解析,那就是自找苦吃——你根本没法精确提取嵌套字段。

jq就是专门干这个的。它像awk一样,但处理的是JSON结构。

# 提取所有日志中的message字段
jq '.message' app.json

# 过滤level为"ERROR"的日志
jq 'select(.level == "ERROR")' app.json

# 提取嵌套字段
jq '.request.headers."User-Agent"' app.json

# 格式化输出(默认就是格式化好的)
jq '.' app.json

我举个例子。有一次线上排查慢查询,日志里记录了每个请求的耗时。用jq一行命令就搞定了:

# 找出耗时超过2秒的请求,只输出时间和耗时
jq 'select(.duration > 2000) | {time: .timestamp, duration: .duration}' app.json

结果一目了然。如果换成grep,你得先匹配"duration",再手工解析后面的数字……想想就头疼。

实战技巧:jq支持管道操作。你可以把多个过滤条件串起来,像流水线一样处理数据。比如:jq 'select(.level == "ERROR") | select(.duration > 1000) | .message',这样就能精确找到“耗时超过1秒的错误请求”。

3.3 Python日志解析库:当命令行不够用时

grep/awk/sed/jq再强,也有力不从心的时候。比如:

  • 需要跨多个日志文件做关联分析
  • 需要复杂的统计计算(比如百分位数、标准差)
  • 需要生成可视化图表
  • 需要定时任务自动分析

这时候,就该Python上场了。我个人最常用的库有三个:

库名 用途 适用场景
re 正则表达式匹配 解析非结构化文本日志
json JSON解析 处理JSON格式日志
pandas 数据分析 大规模日志统计、聚合、可视化

来看一个实际例子。假设我们要分析Nginx访问日志,找出响应时间最慢的10个请求:

import re
from collections import Counter

# 日志格式示例:127.0.0.1 - - [10/Jan/2025:13:55:36 +0000] "GET /api/users HTTP/1.1" 200 2326 0.045
pattern = r'(\S+) .*? \[.*?\] ".*?" \d+ \d+ (\S+)'

slow_requests = []

with open('access.log', 'r') as f:
    for line in f:
        match = re.search(pattern, line)
        if match:
            ip = match.group(1)
            response_time = float(match.group(2))
            if response_time > 1.0:  # 超过1秒
                slow_requests.append((response_time, ip))

# 排序取前10
slow_requests.sort(reverse=True)
for time, ip in slow_requests[:10]:
    print(f"{time:.3f}s - {ip}")

这段代码看起来简单,但实际排查问题时非常有用。我曾在生产环境跑过类似的脚本,发现某个IP的请求响应时间异常高,最后定位到是那个用户的网络延迟问题。

我的建议:能用命令行解决的,别用Python。但一旦涉及多步处理、条件分支、复杂统计,果断上Python。别在shell脚本里写一堆for循环和if判断,那代码维护起来太痛苦了。

3.4 知识体系总览

下面这张图,是我自己总结的日志分析工具选择逻辑。你可以把它当成一个决策树:

日志分析工具选择逻辑 日志文件 纯文本日志 JSON日志 grep:快速过滤 awk:按列统计 jq:字段提取 jq:条件过滤 复杂分析需求? Python + re/json Python + pandas 原则:能用命令行解决的,别上Python。但复杂场景别硬扛,果断换脚本。

3.5 实战:一个完整的分析流程

最后,我分享一个真实案例。有一次线上告警,说某个接口的P99延迟从200ms飙升到了2s。我按以下步骤排查:

  1. 先用grep过滤:grep "/api/orders" access.log | grep "ERROR",发现错误率并没有明显上升。
  2. 再用awk统计:awk '{print $NF}' access.log | sort -n | awk '{count++; sum+=$1} END {print "avg:", sum/count}',发现平均延迟确实高了。
  3. 然后用jq深入:因为日志里记录了每个请求的数据库查询时间,我用jq提取了所有慢查询的SQL语句。
  4. 最后用Python做关联分析:把慢查询和接口延迟做关联,发现某个SQL的执行时间占了总延迟的80%。

整个过程不到20分钟。如果一开始就写Python脚本,光调试就得花半小时。你想想看,工具选对了,效率能差多少?

我的习惯:先用手头的命令行工具快速摸清情况,确定问题范围。如果问题复杂,再用Python做深度分析。别一上来就写脚本,也别一直死磕命令行。