我需要在一大堆 apache 日志中寻找一些请求。我唯一的要求是:
我只需查看来自未包含在我拥有的 50 个 IP 范围列表中的任何 IP 地址的请求。
我怎样才能使用正则表达式 awk grep 或其他东西的任意组合来实现这一点?想不出简单的办法。这个想法是获取每一行,获取第一部分(IP 地址),将其与包含所有范围的文件进行匹配,如果不存在,则显示它。不知道如何去做,所以欢迎任何帮助!
样品:
典型的 http 日志行是
123.456.789.012 - - [22/Oct/2012:06:37:48 +0100] "GET /test/test HTTP/1.1" 302 224 "-" "some user agent/4.3.5"
我的 IP 范围文件中的典型行是
192.168.0.1 - 192.168.0.255
当然,如有必要,IP 范围文件可以转换为 192.168.0.1/24 表示法。好处是所有范围都是 C 类(刚刚注意到),所以我猜只有 IP 地址的前 3 部分可以匹配,这应该足够好了。
答案1
一种简单粗暴的方法是使用 grep。
创建一个文件(范围.txt)你的范围是这样的:
192\.168\.0\.[0-9]*
10\.0\.0\.[0-9]*
要从已有的范围文件创建该文件,可以sed
像这样使用:
sed -n -e 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\) .*$/^\1\\.\2\\.\3\\.[0-9]* /p' your-range-file > ranges.txt
然后使用 grep 排除与该文件中的模式匹配的行,如下所示:
$ grep -v -f ranges.txt apache-log-file.log
或者
$ cat apache-log-file.log | < do some pre cleaning > | grep -v -f ranges.txt
这可以帮助您入门,但如果查询应该经常运行并且在大日志文件上运行,那么它可能不是一个好的解决方案。
祝你好运!
答案2
Log 是您的日志文件,iprange 是包含 iprange 的文件。解决方案的 Perl 部分获取 IP 地址的前 3 个组成部分,如果 ipranges 文件中不存在,则 for 循环将打印它:
for i in `perl -lne 'print $1 if (m/(\d{1,3}\.\d{1,3}\.\d{1,3})\.\d{1,3}/);' log`
> do
> grep -q $i iprange || echo $i;
> done