web-dev-qa-db-ja.com

文字列を省略した場合の並列再帰Grep

問題

結果から文字列を省略しながら、再帰的な並列zgrepを実行できません。

約640GBの圧縮ファイアウォールログをzgreppingしていて、行のほぼ%30に「DuplicateSYN」という文字列があります(これは省略しようとしています)

再帰的並列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を変更して、「重複」という単語を省略した正規表現を使用します(これを行う方法がわかりません)。
  • 640GBのgzip圧縮されたすべてのログファイルで「重複」という単語を含むすべての行を再帰的に削除します(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
3
brakertech

writeの最も簡単な方法は、ファイルに書き込む前に、出力をgrepの別の呼び出しにパイプすることです。

find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt | grep -v Duplicate > /tmp/bar.txt

別のシングルスレッドプロセスでこれを実行するパフォーマンスは、検索によって返されるレコードの数によって異なります。最初の検索に一致する行数が640GBのログのごく一部である場合は、問題にはなりません。

根本的な質問の一部は、この検索全体の最適化に関するものでもあるため、次の2つの大きな追加の拡張機能があることに注意してください。

  1. Grep検索用語には、正規表現ではなく固定文字列を使用します。パターンファイルから円記号を削除し、-Fスイッチをzgrepに追加します。 (単語全体にのみ一致する-wスイッチも良い考えです。)リテラル文字列の検索は、正規表現の検索よりもはるかに高速です。
  2. システムのロケールがUTF-8を使用しているが、データセットがASCIIのみである場合は、コマンドの環境でLC_ALL=Cを設定します。検索は、128文字のASCIIセット内では、約1000倍大きいUTF-8文字セットよりもはるかに高速に動作します。
1
Dan Rice

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による)。

1
Ole Tange