对于 Nginx 的运营和安全监控来说,了解每个 IP 发出请求时所收到的各种状态码分布是一项重要工作。这能帮助识别可能的访问模式、故障源或潜在的攻击尝试。以下是一套详细的步骤和命令,用于分析 Nginx access logs,获取每个 IP 地址的请求状态码概览。
步骤详解
我们的目的是从 Nginx access logs 中提取每个 IP 的请求状态码,并对其出现频次进行总结。
- 提取 IP 和状态码
首先,你需要从日志中同时抓取 IP 地址和状态码信息。这两者分别位于 log 中的第一列和第九列(在默认配置下)。使用 awk 命令可以轻松地做到这一点:awk '{print $1, $10}' /var/log/nginx/access.log - 整理为固定格式
将 IP 和状态码整合到同一列,中间用逗号或其他易于分割的字符隔开,便于后续处理:awk '{print $1 "," $10}' /var/log/nginx/access.log > ip_status_codes.csv - 按 IP 分组并统计状态码
使用sort,uniq, 和awk来按 IP 分组并对每个 IP 下的不同状态码进行统计:sort ip_status_codes.csv | awk -F ',' '{a[$1,$2]++} END {for (i in a) print i, a[i]}' | sort -t',' -k1,1 -k2n上述命令的工作原理如下:
-F ',': 设置逗号作为分隔符;{a[$1,$2]++}: 每次遇到相同的 IP 和状态码对,就增加计数器;END {for (i in a) print i, a[i]}: 循环遍历关联数组打印每个 IP 地址及其对应的状态码及其出现次数;- 最后的
sort: 再次排序,确保结果按照 IP 地址和状态码升序。
- 细化输出
最终,为了更清晰地呈现结果,我们可以再次组织输出格式,使其按 IP 地址和状态码分开显示:awk ' BEGIN {FS=","} NR==FNR {counts[$1][$2]=$3; next} {printf "%s:\n", $0} END { for (ip in counts) { printf "%s\t", ip; for (code in counts[ip]) { printf "%s:%d ", code, counts[ip][code]; } print ""; } } ' ip_status_codes.csv -在这段脚本中,我们首先建立一个多维数组
counts存储 IP 地址和状态码及其对应的次数,然后以友好的格式打印出来。
封装为脚本
为了方便使用,你可以将上述步骤集成到一个 shell 脚本中:
#!/bin/bash
filename="/var/log/nginx/access.log"
awk '{print $1 "," $10}' "$filename" > ip_status_codes.csv &&
sort ip_status_codes.csv | \
awk -F ',' '{a[$1,$2]++} END {for (i in a) print i, a[i]}' | \
sort -t',' -k1,1 -k2n | \
awk '
BEGIN {FS=","}
NR==FNR {counts[$1][$2]=$3; next}
{printf "%s:\n", $0}
END {
for (ip in counts) {
printf "%s\t", ip;
for (code in counts[ip]) {
printf "%s:%d ", code, counts[ip][code];
}
print "";
}
}'
这样,只需运行这个脚本就能得到每个 IP 地址的请求状态码汇总。
注意事项
- 日志文件大小:处理大型日志文件时需谨慎,考虑分批处理或在低流量时间执行分析。
- 日志格式变化:确保 Nginx 日志格式与你的脚本兼容;必要时调整命令中的列索引。
- 自动化分析:考虑定时任务或警报系统以持续监控 IP 请求状况的变化。
通过上述步骤,你可以深入洞察 Nginx 中每个 IP 的请求状态码情况,为进一步的系统诊断、性能优化或安全强化提供坚实的数据基础。