3. 日志分析工具:从命令行到 Python 的实战武器库

日志分析这事儿,工具选对了,事半功倍。我见过不少同事,对着几 GB 的日志文件,还在用鼠标滚轮翻,看得我直着急。其实,用好 grep、awk、sed 这三个老伙计,再加上 jq 和 Python 那几把刷子,大部分问题都能快速定位。

今天我就把这几样东西的「家常用法」给你捋一遍。嗯,都是我在线上环境里真刀真枪用过的。

3.1 命令行三剑客:grep / awk / sed

这三个工具,说白了就是文本处理的瑞士军刀。你不需要背所有参数,记住最常用的那几个就行。

3.4.1 grep —— 最快的过滤器

grep 就是用来「找东西」的。我个人习惯,上来先加个 -i 忽略大小写,再加个 --color 高亮匹配项,看着舒服。

核心用法:

  • grep "ERROR" app.log —— 找包含 ERROR 的行
  • grep -v "INFO" app.log —— 排除 INFO 行
  • grep -E "ERROR|FATAL" app.log —— 匹配多个关键词
  • grep -A 5 -B 5 "NullPointer" app.log —— 显示匹配行前后各 5 行

我的习惯:排查问题时,我一般先用 grep -c "ERROR" 看看错误数量,心里有个底。如果文件太大,记得加 --line-buffered,配合 tail -f 实时过滤。

3.1.2 awk —— 列处理神器

awk 默认按空格或 Tab 切分每一行。我最常用的场景是:从日志里提取某个字段。

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

# 以逗号分隔,提取第 2 列
awk -F',' '{print $2}' csv.log

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

我曾经用一行 awk 命令,从 2GB 的 Nginx 日志里,5 秒钟就统计出了 Top 10 的请求 IP。你想想看,如果用 Python 写脚本,光读取文件就得半天。

3.1.3 sed —— 流式编辑器

sed 用来「改东西」。线上排查时,我经常用它来替换敏感信息,或者清理日志里的乱码。

# 替换文本(全局)
sed 's/old_text/new_text/g' file.log

# 只替换第 3 行到第 10 行
sed '3,10s/ERROR/WARNING/g' file.log

# 删除空行
sed '/^$/d' file.log

# 直接修改文件(小心!)
sed -i 's/password=.*/password=***/g' config.log

避坑指南:我曾经在线上直接用了 sed -i 替换配置文件,结果替换错了,差点把生产环境搞挂。从那以后,我养成了一个习惯:先用 sed 不加 -i 预览结果,确认无误后再加 -i。或者用 sed -i.bak 先备份。

3.2 jq —— JSON 日志的救星

现在很多应用都输出 JSON 格式的日志。用 grep 去搜 JSON?那简直是灾难。jq 就是专门干这个的。

我刚开始用 jq 时,也觉得语法怪怪的。但用顺手后,真香。

# 格式化 JSON 输出
cat log.json | jq '.'

# 提取某个字段
cat log.json | jq '.message'

# 条件过滤
cat log.json | jq 'select(.level == "ERROR")'

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

实战场景:有一次,线上服务报 502,我拿到一段 JSON 日志,里面有个 response_time 字段。我直接用 jq 过滤出所有 response_time 大于 5000ms 的请求,然后按时间排序,很快就锁定了慢查询的 SQL。

jq 还有一个很实用的功能:jq -r 可以输出原始字符串,方便重定向到文件或管道给其他命令。

3.3 Python 日志分析库:re / collections / pandas

当命令行工具搞不定时,就该 Python 上场了。比如需要复杂的关联分析、统计报表,或者要处理多行日志。

3.3.1 re —— 正则表达式引擎

Python 的 re 模块,比 grep 的 -E 灵活得多。我一般用它来解析非结构化的日志。

import re

log_line = "2025-03-21 14:23:45 ERROR [main] NullPointerException at com.example.service.UserService.getUser()"

pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\w+) \[(\w+)\] (.+)'
match = re.match(pattern, log_line)

if match:
    timestamp = match.group(1)
    level = match.group(2)
    thread = match.group(3)
    message = match.group(4)
    print(f"时间: {timestamp}, 级别: {level}, 线程: {thread}, 消息: {message}")

我的习惯:写正则时,我一般先用 regex101.com 在线测试,确认无误再贴到代码里。另外,记得给正则加 r 前缀,避免转义地狱。

3.3.2 collections —— 计数器与默认字典

collections 里的 Counter 和 defaultdict,是我做日志统计时的左膀右臂。

from collections import Counter, defaultdict

# 统计错误类型
error_counts = Counter()
with open('app.log') as f:
    for line in f:
        if 'ERROR' in line:
            # 假设错误类型在行尾
            error_type = line.split()[-1]
            error_counts[error_type] += 1

print(error_counts.most_common(10))

# 按时间分组统计
hourly_errors = defaultdict(int)
with open('app.log') as f:
    for line in f:
        if 'ERROR' in line:
            hour = line[11:13]  # 提取小时
            hourly_errors[hour] += 1

for hour, count in sorted(hourly_errors.items()):
    print(f"{hour}:00 -> {count} 次错误")

你想想看,用 Counter 一行代码就能搞定 Top N 统计,比写一堆 if-else 清爽多了。

3.3.3 pandas —— 结构化分析利器

当日志量达到百万级别时,pandas 的优势就体现出来了。它能把日志当成表格来处理。

import pandas as pd

# 读取日志文件,假设是 CSV 格式
df = pd.read_csv('app.log', sep='\t', names=['timestamp', 'level', 'thread', 'message'])

# 过滤出 ERROR 级别的日志
errors = df[df['level'] == 'ERROR']

# 按小时统计错误数量
errors['hour'] = pd.to_datetime(errors['timestamp']).dt.hour
hourly_counts = errors.groupby('hour').size()

# 找出错误最多的前 5 个小时
print(hourly_counts.sort_values(ascending=False).head(5))

实战案例:有一次,我需要分析一周的 API 网关日志,总共 5000 万行。用 pandas 的 groupby 和 agg 函数,我花了 10 分钟就写完了分析脚本,跑完只用了 3 分钟。如果用手工统计,估计得干到天亮。

3.4 知识体系总览

下面这张图,把今天讲的内容串起来了。你可以把它当成一个「工具选择指南」。

日志分析工具知识体系 日志分析工具知识体系 日志分析工具 命令行三剑客 JSON 日志处理 Python 分析库 grep 过滤 awk 列处理 sed 编辑 jq 查询/过滤 jq 格式化输出 re 正则解析 collections 统计 pandas 分析 选择原则 小文件/快速定位 → 命令行工具 | 结构化/JSON → jq | 复杂统计/自动化 → Python

3.5 工具选择速查表

为了方便你快速决策,我整理了一个对照表。遇到问题时,直接查表就行。

场景 推荐工具 理由
快速搜索关键词 grep 速度最快,支持正则
提取某列数据 awk 默认按分隔符切分,灵活
批量替换文本 sed 流式处理,适合大文件
解析 JSON 日志 jq 原生支持 JSON 结构
复杂正则匹配 Python re 支持分组、回溯等高级特性
统计计数 Counter 一行代码搞定 Top N
大规模数据分析 pandas 支持 groupby、聚合、可视化

我的建议:别想着把所有参数都背下来。记住每个工具最常用的 3-5 个用法,剩下的用到时再查。我干了十年运维,grep 的 -P 参数到现在还得翻手册。

好了,这一章的内容就这些。工具是死的,思路是活的。下次遇到日志问题,先想想:这个场景适合用哪个工具?然后动手试试。嗯,多练几次,你就能像我一样,看到日志就能条件反射地想到对应的命令了。