问题
我无法执行递归并行 zgrep,同时也从结果中省略字符串。
我正在 zgrepping 大约 640GB 的压缩防火墙日志,几乎 %30 的行有字符串“Duplicate SYN”(我试图省略)
递归并行 Zgrep(不省略字符串)- 成功
我能够像这样成功执行并行递归 grep
find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt > /tmp/bar.txt
foo.txt的内容:
10\.10\.0\.28
10\.10\.3\.41
10\.10\.0\.46
10\.10\.5\.47
10\.11\.0\.48
10\.10\.0\.49
10\.144\.41\.145
10\.122\.41\.241
示例输出
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
May 31 02:58:46 ASAFW01 : %ASA-6-302014: Teardown TCP connection 461681145 for DMZ_EXP_INSIDE:10.122.41.241/7400 to inside:10.5.91.50/30378 duration 0:00:00 bytes 0 Failover primary closed
May 31 02:58:47 ASAFW01 : %ASA-6-302013: Built outbound TCP connection 1962428108 for DMZ_EXP_INSIDE:10.122.41.241/7400 (10.122.41.241/7400) to inside:10.11.0.48/33990 (10.11.0.48/33990)
May 31 02:58:47 ASAFW01 : %ASA-6-302014: Teardown TCP connection 1962428108 for DMZ_EXP_INSIDE:10.122.41.241/7400 to inside:10.11.0.48/33990 duration 0:00:00 bytes 3188 TCP Reset-O from DMZ_EXP_INSIDE
May 31 02:58:49 ASAFW01 : %ASA-6-106015: Deny TCP (no connection) from 10.11.0.48/35976 to 10.122.41.241/7400 flags RST on interface inside
May 31 02:58:49 ASAFW01 : %ASA-6-106015: Deny TCP (no connection) from 10.11.0.48/35976 to 10.122.41.241/7400 flags RST on interface inside
我想省略的输出
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
想法
- 修改 foo.txt 以使用省略单词“Duplicate”的正则表达式(不知道如何执行此操作)
- 递归删除所有 640GB gzip 压缩日志文件中包含单词“Duplicate”的所有行(使用 sed?)
递归并行 Zgrep(省略字符串)- 失败
但是,当我尝试从结果中排除某些内容时,我收到错误。
导致错误的命令:
find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt -v Duplicate > /tmp/bar.txt
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
答案1
最简单的方法写grep
这个附加条件只是在写入文件之前通过另一个调用来传输输出:
find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt | grep -v Duplicate > /tmp/bar.txt
在单独的单线程进程中执行此操作的性能将取决于搜索返回的记录数。如果与您的初始搜索匹配的行数只是 640GB 日志的一小部分,那么这应该不是问题。
由于根本问题也部分是关于整体优化此搜索,因此我会注意到您可以进行两项重大的额外增强:
- 使用固定字符串而不是正则表达式作为 grep 搜索项——从模式文件中删除反斜杠并将开关添加
-F
到 zgrep。 (-w
切换到仅匹配整个单词也可能是一个好主意。)搜索文字字符串比搜索正则表达式要快得多。 - 如果您的系统区域设置使用 UTF-8 但您的数据集仅为 ASCII,请
LC_ALL=C
在命令的环境中进行设置。在 128 个字符的 ASCII 集中,搜索速度比在大约 1000 倍大的 UTF-8 字符集中进行搜索要快得多。
答案2
如果您有 GNU Parallel,您可以执行以下操作:
find /var/logs/syslog -name \* -print0 |
parallel --lb -0 'zgrep -f foo.txt {} | grep -v Duplicate' > /tmp/bar.txt
相反,xargs -P
使用 GNU Parallel 的输出保证不会混合行(根据 mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P)。