for x in `cat /var/www/vhosts/example.com/statistics/logs/access_log.processed | awk '{print $1}' | sort | uniq -c | sort -nr | awk {'if ($1 > 2000) print $2'}`;
do
#Works
printf "$x"
#Does not work
printf "$1"
done
我正在尝试阻止尝试超过 2000 个请求的 IP 地址。实际上上面的代码是两部分的组合。
第一的,
cat /var/www/vhosts/example.com/statistics/logs/access_log.processed | awk '{print $1}' | sort | uniq -c | sort -nr
我收集、排序并统计所有 IP 地址。下面是一个示例结果
4565 8.8.8.8
3245 7.7.7.7
然后我迭代每个结果并检查尝试次数是否超过 2000。
awk {'if ($1 > 2000) print $2'}
$1
是尝试次数,$2
是IP。
so$2
被另存为$x
并且可以在 for 循环中使用。但我怎样才能$1
在 for 循环内部使用呢?
答案1
使用while
循环而不是for
,并从 发出多列awk
。
while read x y; do
echo $y $x
done << EOF
example one
example two
EOF
答案2
和bash
都有awk
自己的变量集。其意义和价值都有$1
不同awk
的形式。在您的情况下,您可以将数组传递给然后将其拆分在循环内$1
bash
"$1 $2"
$x
for x in `cat /var/www/vhosts/example.com/statistics/logs/access_log.processed | awk '{print $1}' | sort | uniq -c | sort -nr | awk {'if ($1 > 2000) print $1, $2'}`; do
IFS=" " read first second <<< "$x"
#now $first=$1, $second=$2
done
答案3
为什么要重新发明轮子失败2禁止已经可以做你想做的事了(以及更多)?
使用fail2ban
,您可以创建一个自定义规则,使任何对给定网站(或所有托管网站)的请求都匹配,然后maxretry
将该规则的设置为 2000。
您还可以将该bantime
规则设置为您想要的任何内容(例如,bantime=86400
阻止该 IP 一天)。
默认情况下,它还会记录每个阻止和取消阻止操作,例如在/var/log/fail2ban.log
.
顺便说一句,您可能需要重新考虑您的目标。来自单个 IP 的 2000 个请求实际上并不是很多请求,特别是如果您提供的每个“页面”包含大量图像、css 文件、javascript 文件等。或者如果该 IP 地址是squid
数十或数百个代理(例如正在运行)学校或公司网络上的机器。或对于 ISP。