有一个大型的syslog文件,包含这样的消息:
Dec 15 06:26:34 titan kernel:[1710994.114000] Drop_43 IN = eth0 OUT = MAC = 00:04:23:b7:c1:26:00:06:f6:5f:02:7f:08: 00 SRC = 52.53.123.183 DST = 108.249.31.54 LEN = 44 TOS = 0x00 PREC = 0x00 TTL = 60 ID = 20977 PROTO = TCP SPT = 80 DPT = 1 WINDOW = 16384 RES = 0x00 ACK SYN URGP = 0
我必须找出这些IP访问最多的10个最活跃的IP和打印端口。
管理计算前10个最活跃的IP -
cat syslog| grep SRC | awk '{print$11}' | sort -n | uniq -c | sort -rn | head -10
它给出了类似的东西
2528 SRC = 93.65.51.154 1860 SRC = 162.31.151.223
我还使用此输入计算了大多数访问端口
cat syslog | awk '{FS="DPT="};{print$2}'| awk '{FS=" "};{print $1}'| sort -n| uniq -c| sort -rn| head -10
现在我需要以某种方式将这两者结合起来以正确的方式完成我的解析。有什么想法吗?
答案 0 :(得分:2)
您是否考虑过将数据收集到关联数组中,然后在END块中使用asort()按顺序排序。最后,打印每个数组的前10个条目。您希望我建议一些代码,还是足够灵感?
您的代码中存在许多“犯罪”。第一个是经典的'无用的猫'。但那是厚颜无耻的,我道歉。我想这里的真正意义是,当它可以执行任务的每个组件时,你几乎不使用awk。无需grep,sort,uniq,head等。您是否想尝试将其全部转换为awk脚本,或者您是否需要具体的帮助?
编辑:这是我打了一个剧本。我生成了一个与您的数据匹配的1000行测试用例文件。将下面的代码示例按顺序剪切粘贴到一个名为yourname
的文件中,您就可以将其作为运行
./yourname syslog
并且不要忘记运行chmod a+rx yourname
以使其可执行。
顺便说一句,我没有按照我的第一个建议使用asort(),因为它同时被证明是不必要的,也比它的价值更麻烦,原因我不会进入这里。
开始:
#!/usr/bin/gawk -f
任何以#开头的脚本!将运行指定的命令而不是普通的shell。允许参数; awk需要-f被告知要读取哪个文件。它也将由shell提供此文件的名称。幸运的是,awk将#视为评论,这很方便......
首先要收集数据。我正在收集两个阵列;第一个计算每个IP地址的命中数,第二个计算每个IP地址的每个端口的命中数。
此处显示的第一个模式仅过滤感兴趣的行。如果您的系统日志中有其他意外匹配的行,则您需要使/SRC=/
模式足够强大且仅与您选择的行完全匹配。
在块中,字段在=上拆分,以便只能将普通数字存储在数组中。
/SRC=/ {
split($11, ipa, /=/)
split($20, porta, /=/)
IP = ipa[2]
port = porta[2]
IPhits[IP]++
IPports[IP][port]++
}
将对与模式匹配的每一行执行该块。当awk到达结尾时,它将运行标有END
的任何块。
当for ... in
用于迭代数组时,PROCINFO可用于控制项目的序列。我将它设置为按数组元素的降序运行,这很方便地适合两个循环。
我有一个简单的计数器将IP限制为前10个IP地址,另一个计数器限制每个IP打印的端口数量。由于PROCINFO已设置,因此两个循环将首先运行最高值。
要打印的字符串一次构建一个。您可能已经意识到字符串只是通过将它们放在彼此附近而粘在一起 - 这就是buf = buf sep p
行。
END {
PROCINFO["sorted_in"] = "@val_num_desc"
i = 0
for(ip in IPhits) {
# limit of 10 IP addresses to report
if(i++ == 10) break
buf = ip
sep = " - "
j = 0
for(p in IPports[ip]) {
# limit of 10 ports per IP
if(j++ == 10) break
buf = buf sep p
sep = " "
}
print buf
}
}
那里的任何东西都没有意义吗?