シェルスクリプト - Awk最適化

シェルスクリプト - Awk最適化

Broネットワークログ解析スクリプトを最適化するのに役立ちます。背景は次のとおりです。

私は多数の兄弟ログを持っていますが、私の範囲(複数可変長サブネット)のIPを照会することにのみ興味があります。

したがって、私が探しているIP範囲に一致する正規表現パターンを含むテキストファイルがあります。

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

(scope.txtには、正規表現パターンの追加IP範囲の最大20行が含まれています。)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ログは1時間あたり約100MBであるため、現在のスクリプトは1時間分のログデータを解析するのに約10〜20分かかります。 1日の記録には最大3時間かかることがあります。

私は40個の単一のawkステートメントを使用することを検討しましたが、別のIP範囲で同じスクリプトを使用できるように別のscope.txtファイルが必要だったので、そうしないことにしました。

また、複数のconn.logファイル(zcat conn.*.log.gzなど)でzcatを試みましたが、出力ファイルが1 GBを超えて時間ごとのログを残したかったのです。

答え1

awkを介してログファイルを一度だけ渡すと、多くの利点が得られます。これは、すべての正規表現を1つにまとめることを意味します。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 は、各正規表現行の周りの合計を閉じるペアに/^置き換え、行の末尾に 1 を追加し、1 行の結果をすべてファイルに保存します。したがって、ファイルはすべてORで連結されたパターンです。欠落しているコンテンツは、スキーマファイルを変数として読み取る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できるようにスキーマファイルを指定します。 あなたの質問によると、これはあなたに必要なものであり、あなたは多くのgrep -f"or"を含むAwkコマンドを書く必要なしにファイルから取得した複数の検索パターンを使うことができます。


sort | uniq特定のオプションフラグをsort -u使用する必要がない限り、通常は置き換えることができます。uniqこの場合はそれを必要としないので、より単純な形式を使用しましたsort -u

関連情報