按字段统计日志的方法
日志分析的基本功是把每行拆成字段再聚合。awk 默认按连续空白分词,$1 是第一个字段,$NF 是最后一个字段,NF 是字段总数,$(NF-3) 表示从末尾倒数第四个,这种相对定位能适配位置随版本微调的日志。配合 sort、uniq -c、sort -rn 组成流水线,就能算出 Top IP、状态码分布、每小时的请求量。前提是先 head 几行看清格式:不同 log_format 或 sshd 版本的列位置并不相同,照抄教程里的列号是常见错误来源。
基本信息
| 适用平台 | Linux/macOS(gawk、mawk、BSD awk 的 -F 与内置变量通用) |
|---|---|
| 命令语法 | awk -F'分隔符' '条件{动作}' 文件 |
| 常用内置变量 | $0 整行 $1..$N 各字段 NF 字段数 NR 行号 $(NF-k) 从末尾相对定位 |
| 配套工具 | sort 排序、uniq -c 计数、sort -rn 数值降序、head 截取 |
| 权限说明 | 读日志文件需相应权限,secure 或 auth.log 一般要 sudo |
典型使用场景
- 访问统计:从 Nginx 访问日志算出 Top IP 与 Top URL
- 安全排查:统计认证失败来源 IP,判断是否被撞库
- 时间分布:按小时聚合请求量,定位流量高峰与异常时段
- 错误聚焦:筛出 5xx 状态码的请求,按接口路径归因
- 性能粗看:提取响应时间字段做排序,找出最慢的接口
常用示例
常用示例
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
sudo grep 'Failed password' /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
awk -F'[: ]' '{print $4":"$5}' access.log | uniq -c | head -n 24
awk '$9 >= 500 {print $7}' access.log | sort | uniq -c | sort -rn | head
awk '{print $NF}' resp.log | sort -rn | head # 假设末列是耗时,先确认格式
head -n 5 /var/log/nginx/access.log # 动手前先确认列位置Nginx combined 列位参考
| 字段 | 典型列 | 用途 |
|---|---|---|
| 客户端 IP | $1 | Top IP 统计、封禁候选 |
| 时间 | $4 | 按时间窗口过滤,注意行首方括号 |
| 请求行 | $6 $7 | 包含引号,URL 与协议的分析要用 -F'"' 更稳 |
| 状态码 | $9 | 5xx 比例与错误接口定位 |
| 响应体大小 | $10 | 流量归因,- 表示无响应体 |
列号依赖具体 log_format:先 head -n 5 看样本,再决定 awk 的字段号。请求行含引号与空格时,用 -F'"' 按引号切分比按空格切分可靠得多。
日志被 logrotate 切割后历史在 .gz 文件里,统计要覆盖全部窗口:zcat /var/log/nginx/access.log*.gz 后再接 awk,或直接 zgrep。
统计写法要点
| 目标 | 核心写法 | 注意 |
|---|---|---|
| 按状态计数 | 对指定字段累加计数 | 先确认字段位置 |
| 按来源排名 | 计数后交给数值排序 | 不做数值排序会得到字典序 |
| 耗时分布 | 按区间分桶累加 | 先明确单位与口径 |
| 时间窗过滤 | 在起始块内判断时间 | 避免逐行做复杂字符串处理 |
| 输出占比 | 计数除以总数 | 注意整除与浮点显示 |
写统计前先取几行样例确认字段位置:分隔符、被引号包住的字段、带空格的用户代理都会影响切分方式。空格分隔的日志适合快速统计,格式固定且含引号时应改用能识别引号的解析方式,否则统计口径会悄悄偏掉。