Shell 脚本 - Awk 优化

Shell 脚本 - Awk 优化

我正在寻求一些帮助来尝试优化兄弟网络日志解析脚本,这是背景:

我有大量的兄弟日志,但我只对查询我的范围内的IP(多个可变长度子网)感兴趣。

因此,我有一个包含正则表达式模式的文本文件来匹配我正在查找的 IP 范围:scope.txt:

/^10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5])$/

(scope.txt 在正则表达式模式中包含最多 20 行其他 IP 范围)findInScope.sh:

#!bin/sh
for file in /data/bro_logs/2016-11-26/conn.*.log.gz
do
    echo "$file"
    touch /tmp/$file
    for nets in $(cat scope.txt)
    do
        echo "$nets"
        zcat $file | bro-cut -d | awk '$3 ~ '$nets' || $5 ~ '$nets'' >> /tmp/$file
    done
    sort /tmp/$file | uniq > ~/$file
    rm /tmp/$file
done

作为更多背景,原始 bro conn 日志每小时约为 100MB,因此我当前的脚本大约需要 10-20 分钟来解析一小时的日志数据。一天的日志最多可能需要 3 小时。

我考虑过使用 40 个 or 的单个 awk 语句,但决定不想这样做,因为我想要一个单独的scope.txt 文件,以便对不同的 IP 范围范围使用相同的脚本。

我还在多个 conn.log 文件(即 zcat conn.*.log.gz)上尝试了 zcat,但输出文件最终超过 1GB,我想保持每小时日志完整。

答案1

只需通过 awk 传递一次日志文件,您就会获益匪浅。这意味着将所有正则表达式合并为一个。如果您不想在scope.txt文件中执行此操作,请在调用 awk 之前执行此操作。例如,

sed <scope.txt 's|^/\^|(|; s|\$/$|)|; $!s/$/|/' | tr -d '\n' >pattern

zcat $file | bro-cut -d |
awk '
BEGIN{ getline pat <"pattern"; pat = "^(" pat ")$" }
$3 ~ pat || $5 ~ pat
'  >~/$file

sed 将每个正则表达式行周围的/^和替换$为一对封闭的,在该行的末尾()添加一个,并将结果全部放在一行中放入 file 中。因此,该文件是所有模式或运算在一起的。缺失的内容被添加到 awk 脚本语句中,该语句将模式文件读取到变量 中。|pattern^(...)$BEGINpat

上面的内容替换了您的内部for循环,并且sort|uniq.

答案2

最简单的答案是使用scope.txt稍作修改的 ,作为模式文件,并使用zcat | grep(或仅zgrep) 来获取您需要的行。

首先,修改您的scope文件以更改:

/^10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5])$/

进入:

(^|[^0-9.])(10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5]))($|[^0-9.])

要轻松做到这一点,您可以使用:

sed -e 's:^/\^:(^|[^0-9.])(:' -e 's:\$/$:)($|[^0-9.]):' scope.txt > grepscope.txt

然后,进行搜索:

zgrep -Ehf grepscope.txt /data/bro_logs/2016-11-26/conn.*.log.gz | less

或者,因为您希望每个文件的输出单独存储:

for f in /data/bro_logs/2016-11-26/conn.*.log.gz; do
    zgrep -Ehf grepscope.txt "$f" | sort -u > ~/"${f##*/}"
done

另请注意,“for”循环变量$f将包含全部的依次到每个文件的路径;为了避免在尝试将输出定向到~/"$f"(这将引用您的主目录中可能不存在的子目录)时出现的错误~/data/bro_logs/2016-11-26,我们删除路径名中最后一个斜杠之前的所有内容,只使用基本名称每个日志文件的。


值得一提的标志zgrep

-E指定扩展的正则表达式,以便模式中的括号不需要转义。

-h禁止将文件名打印为每个匹配行的前缀。 (您可以在for循环版本中省略此选项,因为默认情况下grep仅在搜索多个文件时打印文件名,如我指定的第一个命令中所示,但将其保留在两个版本中不会造成任何损害。)

-f让您能够指定一个模式文件。 根据您的问题,这正是您所需要的,并且 usinggrep -f允许您使用从文件中获取的多个搜索模式,而无需构建带有大量“或”的 Awk 命令。


sort | uniq通常可以替换为sort -u,除非您需要使用某些uniq选项标志。在这种情况下你不需要,所以我使用了更简单的形式sort -u

相关内容