【问题标题】:Parsing syslog to count specific values解析 syslog 以计算特定值
【发布时间】:2015-02-13 16:02:40
【问题描述】:

得到一个大的 syslog 文件,其中包含类似这样的消息:

12 月 15 日 06:26:34 泰坦内核:[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

我必须找出 10 个最活跃的 IP 并打印这些 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

现在我需要以某种方式将这两者结合起来以正确完成解析。有什么想法吗?

【问题讨论】:

  • 你的预期输出是什么?
  • 预期输出应类似于 -
  • 我不明白为什么要使用sort -n 对非数值进行排序(SRC=)
  • 你有没有尝试一些新的代码来结合这两个?
  • (command1 ; command2) > output

标签: bash parsing awk


【解决方案1】:

您是否考虑过将数据收集到关联的数组中,然后在 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 地址的每个端口的命中数。

此处显示的第一个模式仅过滤感兴趣的行。如果您的 syslog 有其他意外匹配的行,您需要使 /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,因此两个循环都将首先运行最高值。

要打印的字符串一次构建一个。您可能知道字符串在 awk 中只需将它们彼此靠近就可以粘合在一起 - 这就是 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
    }
}

里面有什么不合理的地方吗?

【讨论】:

    猜你喜欢
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多