这个场景解决什么
TopN 统计在命令行里有固定套路:抽字段、排序、去重计数、再排序截断。命令看着长,但每一步只做一件事,出问题时能逐段定位。日志分析中绝大多数问题都是这四步的排列组合——Top 来源 IP、Top 请求路径、Top 状态码、Top 用户代理,换个字段就是另一个维度。
基本信息
| 场景 | 任意维度的 TopN 排行统计 |
|---|---|
| 固定组合 | awk 或 cut 抽字段 → sort → uniq -c → sort -rn → head |
| 关键前提 | uniq 只能合并相邻重复行,所以在它之前必须排序 |
| 数据规模 | 单机日志按天切割后一般几十到几百 MB,这套组合足够快 |
典型使用场景
- 流量来源分析:找出访问量最大的来源 IP,判断是正常业务还是异常扫描
- 热点接口定位:Top 请求路径往往直接指向需要优化的接口
- 错误分布:按状态码分组统计,快速看出 5xx 集中在什么时间与什么接口
- 压测结果核对:压测后统计响应码与路径分布,验证流量模型是否符合预期
- 安全巡检:Top User-Agent 与 Top 路径组合起来,能看出扫描器的特征
三个典型 TopN
三个典型 TopN
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 # Top IP
grep -o 'GET [^ ]*' access.log | awk '{print $2}' | sort | uniq -c | sort -rn | head # Top URL
awk '{print $9}' access.log | sort | uniq -c | sort -rn # 状态码分布
awk '$9 ~ /^5/ {print $7}' access.log | sort | uniq -c | sort -rn | head -20 # 5xx 集中在哪些路径
awk '{print $9, $1}' access.log | sort | uniq -c | sort -rn | head # 状态码与来源的组合排行压缩日志与一站式写法
压缩日志与一站式写法
zcat access.log.*.gz | awk '{print $1}' | sort | uniq -c | sort -rn | head
zgrep -h 'POST /api' access.log*.gz | awk '{print $1}' | sort | uniq -c | sort -rn | head
awk '{c[$1]++} END {for (k in c) printf "%8d %s\n", c[k], k}' access.log | sort -rn | head # 不用 uniq,一次聚合每一步的作用与常见错误
| 步骤 | 作用 | 常见错误 |
|---|---|---|
| awk 抽字段 | 从每行取出目标维度 | 字段号数错,得到空值或整行 |
| sort | 把相同取值排到一起 | 漏掉这一步,uniq 无法正确合并 |
| uniq -c | 统计相邻重复行的次数 | 输出格式是「次数 值」,后续排序要看第 1 列 |
| sort -rn | 按次数做数值降序 | 漏了 -n 会按字符串排序,10 排在 9 前面 |
| head -N | 取前 N 条 | 在管道中提前退出会让上游收到 SIGPIPE,属正常现象 |
压缩日志不需要先解压:zcat 与 zgrep 可以直接把归档内容喂进管道,处理几天的滚动日志时能省掉一大步磁盘开销。
排序里的数值选项不能省。sort -rn 与 sort -r 的结果完全不同:后者按字符串比较,会出现 9 排在 100 前面的假排行,越看越不对劲。