如何从Access Log中筛选每秒请求数超10的IP地址
解决方案:从Access Log筛选每秒请求≥10的IP
核心思路
要实现按「IP+秒级时间戳」统计请求数并筛选出符合条件的IP,需完成三个核心步骤:
- 从日志中提取IP地址和精确到秒的时间戳作为统计维度
- 对每个IP+时间戳的组合累计请求次数
- 过滤出请求次数≥10的结果,同时补充User Agent信息
命令实现
1. 基础版(仅输出IP、时间戳、请求数)
如果不需要User Agent补充信息,可使用简化命令:
awk '{ # 提取IP地址(日志第一个字段) ip = $1; # 提取秒级时间戳:从带[]的时间字段中截取到秒的部分 timestamp = substr($4, 2, 20); # 以IP+时间戳为键累计请求数 count[ip, timestamp]++; } END { # 遍历统计结果,筛选请求数≥10的条目 for (key in count) { if (count[key] >= 10) { split(key, parts, SUBSEP); # 输出格式:IP\t时间戳\t请求次数,按请求数降序排序 print parts[1] "\t" parts[2] "\t" count[key]; } } }' /www/logs/www.example.com-access.log | sort -k3,3nr
2. 完整版(包含User Agent补充信息)
如果需要同时展示对应IP+时间戳的唯一User Agent,沿用你原命令的-F\"分隔逻辑:
awk -F\" '{ # 提取IP(第一个双引号前的字段,取空格分隔的第一部分) ip = $1; gsub(/^[[:space:]]+|[[:space:]]+$/, "", ip); # 清理IP前后的空格 # 提取秒级时间戳:从第一个双引号前的时间字段中截取到秒 timestamp = substr($1, index($1, "[")+1, 20); # 提取User Agent(和你原命令逻辑一致,取第6个双引号分隔字段) ua = $6; # 累计请求数 count[ip, timestamp]++; # 去重记录User Agent if (!ua_map[ip, timestamp, ua]) { ua_map[ip, timestamp, ua] = 1; ua_list[ip, timestamp] = ua_list[ip, timestamp] ? ua_list[ip, timestamp] ", " ua : ua; } } END { # 输出符合条件的结果,格式化显示 for (key in count) { if (count[key] >= 10) { split(key, parts, SUBSEP); printf("IP: %s\n时间戳: %s\n请求次数: %d\n关联User Agent: %s\n\n", parts[1], parts[2], count[key], ua_list[key]); } } }' /www/logs/www.example.com-access.log | sort -k3,3nr
关键细节说明
- 时间戳提取:
substr($4, 2, 20)适用于常见的Nginx/Apache日志时间格式(如[10/Oct/2024:14:35:22 +0800]),如果你的日志时间格式不同,需调整substr的起始位置和长度以匹配秒级时间范围。 - Unix时间戳适配:如果需要统一时间格式,可将字符串时间戳转换为Unix秒级时间戳,避免格式差异问题(需提前定义月份映射表,用
mktime函数转换)。 - User Agent去重:通过
ua_map字典实现同一IP+时间戳下的User Agent去重,避免重复展示相同的客户端标识。
内容的提问来源于stack exchange,提问作者shurc
相关产品推荐
相关产品推荐

