.gz形式のいくつかのログファイルを取得するスクリプトがあります。スクリプトにクエリを提供すると、その用語に対してzgrepsを実行し、行の先頭からトランザクションIDを取得し、同じファイルを再度zgrepsしてそのトランザクション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
ファイルの圧縮を2回解いたということです。これらのファイルのサイズは100 MBから500 MBです。
スピードを上げる方法はありますか?また、役に立たないことは、ログファイルが複数のフォルダにまたがって分割されていることです。これはKubernetesに関連しているため、1日中のすべてのログがほぼ1つのファイルにあることはほとんどありません。これが私がファイル名をつかむ理由です。トランザクション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または同様のものを検索していますが、1行にしか表示されないようです。したがって、XMLの各リンク行の前に11桁の数字であるトランザクションIDを取得します。
したがって、最終的に行の1つに最初のクエリを含む取引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
これにより、各ファイルの圧縮が一度だけ解放されます。複数のキーワードを一致させるには(各キーワードに対してプログラムを一度実行しないために)-f
inを使用してからgrep
出力を分割します。たとえばawk
。