awk '{print $1}' access.log | sort | uniq -c | sort -rn取第 1 列 IP,统计每个出现次数,按次数倒序。
约 1276 字大约 4 分钟
2026-05-14
前面几篇讲了单个工具,这篇把它们拼起来解决真实问题:从一份访问日志里,算出哪个 IP 请求最多、哪个接口 500 最频繁、错误集中在哪个时间段。这套“筛 → 取 → 统计”的组合拳,是日志排查的核心手艺。
用 grep、awk、sort、uniq 组合统计日志里的 IP、状态码、错误分布,掌握“先看格式、再筛、再取、再统计”的固定套路。
awk '{print $1}' access.log | sort | uniq -c | sort -rn取第 1 列 IP,统计每个出现次数,按次数倒序。
awk '{print $9}' access.log | sort | uniq -c取状态码列,看 200/404/500 各有多少。
grep ' 500 ' access.log | awk '{print $7}' | sort | uniq -c | sort -rn先筛 500 行,再取 URL 列统计。
grep -c ERROR app.log快速数一共有多少条错误,先有个量级概念。
动手统计前,先 head 几行,数清字段。比如典型的 Nginx access.log:
192.168.1.1 - - [10/May/2026:10:00:01 +0800] "GET /api/users HTTP/1.1" 200 1234
$1 $4 $6 $7 $8 $9 $10awk 默认按空格拆列,所以 $1 是 IP、$9 是状态码、$7 是 URL。不同服务的日志格式不一样,列号也不一样——不先看清就写 $9,很可能取错列。
几乎所有日志统计都是这三步:
grep " 500 " access.log \ # ① 筛:缩小到你关心的行
| awk '{print $7}' \ # ② 取:抽出要统计的那一列
| sort | uniq -c | sort -rn # ③ 统计:计数并按次数排序grep 把范围缩小(某状态码、某时间段、某关键词)awk '{print $N}' 抽出你要统计的字段sort | uniq -c 计数,再 sort -rn 排出排行榜记住这个骨架,剩下的只是换 grep 的关键词和 awk 的列号。
# 访问量最高的 10 个 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
# 状态码分布(看 4xx/5xx 占比)
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 哪些 URL 在报 500
grep ' 500 ' access.log | awk '{print $7}' | sort | uniq -c | sort -rn
# 错误按小时分布(截取时间戳的小时部分)
grep ERROR app.log | awk '{print $1}' | cut -d: -f1 | uniq -c不止能取列,awk 也能在取列时直接做条件和计算,省掉 grep:
# 直接统计状态码 >= 500 的请求数
awk '$9 >= 500 {count++} END {print count}' access.log
# 按状态码分组计数(awk 一条顶 sort|uniq -c)
awk '{c[$9]++} END {for (k in c) print c[k], k}' access.log | sort -rn简单统计用 sort | uniq -c 直观;逻辑复杂一点(条件、求和、分组)就让 awk 一条搞定。
uniq -c 告诉你“某 IP 出现了 5000 次”——但这是攻击、是爬虫、还是正常的负载均衡健康检查?数字本身不会回答。拿到排行榜后,要回到原始日志看上下文:
grep "192.168.1.1" access.log | head -50 # 看这个 IP 到底在请求什么把统计当成“缩小范围的工具”,而不是“给出答案的工具”。
大日志先限定范围,别全量裸跑
对几个 GB 的日志直接 sort 整个文件,会吃光内存、拖慢机器。先用 grep、--since 或 tail 把范围缩小再统计。实时滚动的日志用 tail -f ... | grep(见 grep 速查)。还有,统计期间日志是排查证据,只读不要清——要清理空间见 磁盘空间排查。
| 误区 | 更稳妥的做法 |
|---|---|
不看日志格式直接套 $9 之类的列号 | 先 head 几行数清字段,不同服务列号不同 |
对几个 GB 的日志全量 sort | 先 grep / 时间区间缩小范围,再统计 |
把 uniq -c 的数字直接当根因 | 回到原始日志看上下文,统计只是线索 |
| 复杂条件统计还在堆 `grep | awk |
版权归属:Shuo Liu