运行多个 zgrep,寻求性能改进

运行多个 zgrep,寻求性能改进

我有一个脚本可以搜索一些日志文件,所有这些文件都是 .gz 格式。我向脚本提供一个搜索词,它会 zgreps 查找该词,然后从该行的开头获取事务 ID,然后重新 zgrep 相同的文件,以便拉回该事务 ID 的所有行。消除输出中的一些噪声。

while read -r line
do
        rgx="^(.*?)(\.log\.gz)"
        fn=$(echo $line | grep -oP $rgx)
        rgx="(\d{11})"
        trid=$(echo $line | grep -oP $rgx)
        rgx="(\w{3} \d{2} ).*($trid).*"
        zgrep -ohP "$rgx" $fn
done < <(zgrep -oP $regex $path)

这里的问题是它很慢,我的理解是 zgrep 实际上只是在运行gzip -cdfq,所以它解压缩文件两次?这些文件的大小从 100MB 到 500MB 不等。

有什么办法可以加快速度吗?同样毫无价值的是,日志文件被分割在一堆不同的文件夹中,这与 Kubernetes 有关,因此一天的所有日志几乎永远不会只在一个文件中 - 这就是为什么我要抓取文件名以及交易 ID,因此我不会过多地检查每个文件。

这是公司管理的服务器,所以我无法安装任何额外的东西。

日志中的每一行都以以下格式开头,后跟消息

2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785)

在本例中,11 位数字 26122393785 是交易 ID。日志消息主要由 XML 组成 - 我正在 XML 内容中搜索某些内容,通常是 URL 或类似内容,显然它只出现在一行中。因此,我获取了事务 ID,它是 XML 的每个链接行之前的 11 位数字。

因此,最终,我想找到包含交易 ID 的所有行,其中其中一行包含初始搜索词。

所以如果搜索词是 google,我想返回

2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785) <xml>here
2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785) <url>google.co.uk</url>
2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785) end</xml>

答案1

如果您手边确实没有 XML 解析器,我建议您使用 NUL 字节装饰 XML 块,然后使用 .grep 关键字-z

#!/bin/bash
KEYWORD=google

for file in *.log.gz ; do
    zcat "$file"  |\
    sed -e 's|^.*<xml>|\x00&|' -e 's|</xml>$|&\x00|' |\
    grep -z "$KEYWORD" | tr -d '\0'
done

这样每个文件只解压缩一次。如果您想匹配多个关键字(为了不每个关键字运行一次程序),请使用-fin grep,然后分割输出。例如与awk.

相关内容