747 字
约 2 分钟
9
S15-J01 · 文本三剑客:grep / sed / awk 与日志分析
适用读者:看日志全靠肉眼扫的人。
前置:S15-B02。
实测环境:Ubuntu 24.04 / GNU awk(2026-11-05)。
覆盖旧文:—(E 驱动;旧文未覆盖 awk 字段解析)
覆盖扩展:E-S15-004(字段与 NF)、E-S15-005(awk 聚合)。
上一篇:S15-B06 · 时间、时区与系统信息
下一篇:S15-J02 · 定时任务与开机自启。
1. 一句话结论
grep 找行、sed 改行、awk 拆字段。日志分析的关键不是命令,而是"先确认字段编号,再写聚合"。
实测日志(access.log,3 行):
10.0.0.1 - - [05/Nov/2026:10:00:01] "GET /a HTTP/1.1" 200 512
10.0.0.2 - - [05/Nov/2026:10:00:02] "POST /b HTTP/1.1" 500 128
10.0.0.1 - - [05/Nov/2026:10:00:03] "GET /c HTTP/1.1" 404 0
2. 先验字段,再写 awk(E-S15-004)
awk 'NR==1{print "NF="NF; for(i=1;i<=NF;i++) print i": "$i}' access.log
实测输出:
NF=9
1: 10.0.0.1
2: -
3: -
4: [05/Nov/2026:10:00:01]
5: "GET
6: /a
7: HTTP/1.1"
8: 200
9: 512
关键发现:[日期:时间] 中间没有空格 → 只占 1 个字段,所以:
$8= 状态码$9= 字节数
"为什么不能凭直觉用 $9 当状态码"——我第一次就是这么错的(实测拿到 0/128/512,那是字节)。
3. 三个最常用的分析(实测)
状态码分布:
awk '{c[$8]++} END{for (k in c) print k, c[k]}' access.log | sort
# 200 1
# 404 1
# 500 1
字节总量:
awk '{s+=$9} END{print "total bytes:", s}' access.log
# total bytes: 640
5xx 计数:
awk '$8 ~ /^5/ {n++} END{print n+0}' access.log
# 1
按 IP 聚合排序:
awk '{c[$1]++} END{for (k in c) print c[k], k}' access.log | sort -rn
# 2 10.0.0.1
# 1 10.0.0.2
4. grep 与 sed 的分工(E-S15-005)
| 需求 | 命令 |
|---|---|
| 过滤含关键字的行 | grep -c "ERROR" app.log |
| 上下文 | grep -C 3 "Exception" app.log |
| 排除 | grep -v "DEBUG" |
| 替换并输出(不改文件) | sed 's#/b#/BETA#' f |
| 原地替换 | sed -i.bak 's/a/b/' f(先备份) |
实测(sed):
sed 's#/b#/BETA#' access.log | grep BETA
→ ... "POST /BETA HTTP/1.1" 500 128
5. 五个误区
| 误区 | 真相 |
|---|---|
"凭直觉用 $9 当状态码" |
先 print NF 确认(实测是 $8) |
"sed -i 不用备份" |
加 .bak 或用 -i.bak |
"grep 能统计" |
复杂聚合要 awk |
"awk 只能处理 CSV" |
任意分隔文本(-F) |
| "日志分析要装工具" | 三剑客 + sort 够用 |
6. 自检
- 为什么"先验字段"是 awk 的第一步?
- 实测里状态码是第几字段?字节呢?
- 统计状态码分布的命令?
grep -C 3做什么?sed -i的风险怎么规避?
7. 下一篇
S15-J02 · 定时任务与开机自启
文本处理讲完,下一篇讲"让脚本按时跑":crontab 的六个坑。
本篇属于系列《S15 · Linux 与运维》。扩展点 E-S15-004/005。全部计数为 Ubuntu 24.04 实测(3 行样例日志)。
S15-J01 · 文本三剑客:grep / sed / awk 与日志分析
https://www.clxhxhhr.top/posts/5395/ 评论
0 条
还没有评论,先写一条吧。