所以我试图通过 https 来追踪在我们的网络上浏览色情内容的人。该模式很容易看出,在我们的 Bro 日志的 HTTP 标头中,连续 15 个以上的图像点击量没有引用网址。
Bro 中的相关列是 $3 = 主机 IP、$11 = 引用者、$14 = 文件大小和 $27 = mime 类型。
因此,我目前正在使用...
awk -F "\t" '$11 ~ /^\-$/ && $14 > 100000 && $27 ~ /^image/'
我想做的是知道是否有一种方法,仍然在单行命令中运行一个子命令,告诉 awk 仅打印 $3 中的 IP 出现 >= 15 次的行。
我的猜测是我必须创建一个 awk 程序来执行类似的操作。我希望这里有一个高手可以帮助我避免这种情况。我不反对使用另一个正则表达式命令,如果它能更好地工作的话(perl、grep、egrep、agrep、bro-cut)。
更新:解释这一点的最佳方式是通过 Excel 术语。awk 是否有类似 countif Excel 函数的功能?=countif(C1,C:C)>15
样本日志:
1443534069 CGAdXyZgN3wVwihi6 123.456.789.012 59713 93.184.216.98 80 1 GET 40.media.tumblr.com /1fbe50fff7a17f84acdc30b03d9b6335/tumblr_nvf1dfH8oz1tco00do1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 89522 200 OK - - - (empty) - - - - - FIGAv51OT15ak4eDCl image/jpeg
1443534069 CkST1DjXDkCBDYhYa 123.456.789.012 59712 93.184.216.98 80 1 GET 40.media.tumblr.com /e8f958e0dcd3eb419035a8d3271d07e8/tumblr_npr5drTCOO1qk489oo1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 83743 200 OK - - - (empty) - - - - - FWRWZX2XgQQqfm9OMe image/jpeg
1443534069 C8GvXwqAiR84PGGkk 123.456.789.012 59714 93.184.216.98 80 1 GET 40.media.tumblr.com /0b80deef543f6da28b48db0578fb3bd4/tumblr_n0chjkQICf1qeu577o1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 70530 200 OK - - - (empty) - - - - - FOHdJ62uCU30UE9VYg image/jpeg
1443534069 CMXgz73HlqL5Z0WVR7 123.456.789.012 59715 54.230.193.223 80 1 GET 36.media.tumblr.com /547822945f762adb310bb966c1f9c886/tumblr_nv3xgebHVH1sbsr1vo1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 67589 200 OK - - - (empty) - - - - - FmaN4d2eimhA2CpEmd image/jpeg
答案1
此 perl 脚本将符合条件(“image/”,> 100000 字节,referrer = '-')的每个日志行存储在由 IP 地址作为键控的数组哈希中。在脚本末尾,它打印出每个包含超过 14 个条目的 IP 地址的每个数组行。
它使用大量内存,但不如存储每个输入行那么多。
您可以将其压缩为一行,但您只会无缘无故地使其不可读/不可调试。
#! /usr/bin/perl
use strict;
my %LOGLINES = ();
while (<>) {
next unless (/\bimage\//);
my @F=split("\t");
next unless ($F[10] eq '-');
next unless ($F[13] > 100000);
push @{ $LOGLINES{$F[2]} }, $_;
};
foreach my $key (sort keys %LOGLINES) {
print @{ $LOGLINES{$key} } if (scalar @{ $LOGLINES{$key} } > 14);
}
请注意,perl 数组是从 0 开始的,而不是从 1 开始的。因此字段编号与您指定的字段编号偏移 -1。
这是另一个版本,它不使用尽可能多的内存,因为它只为它看到的每个 IP 地址存储最多 15 行,然后它开始打印它看到的匹配行。缺点是输出不按 IP 地址排序,但这可以通过管道到sort -t $'\t' -k2
.
#! /usr/bin/perl
use strict;
my %LOGLINES = ();
my %count = ();
while (<>) {
next unless (/\bimage\//);
my @F=split("\t");
next unless ($F[10] eq '-');
next unless ($F[13] > 12000);
$count{ $F[2] }++;
if ($count{ $F[2] } == 15) {
print @{ $LOGLINES{$F[2]} }; # print all the log lines we've seen so far
print $_; # print the current line
} elsif ($count{ $F[2] } > 15) {
print $_; # print the current line
} else {
push @{ $LOGLINES{$F[2]} }, $_; # store the log line for later use
}
};