よっしー
こんにちは。よっしーです(^^)
今日は、bashを利用したテキストの抽出方法についてご紹介します。
背景
MonologのUidProcessorを利用して、ログにリクエストを識別するuidを付与しています。例えば、下記のような出力になっています。
2023-09-06T14:16:50.611759+00:00 fd2b5fb DEBUG GET localhost/ 10 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
2023-09-06T14:16:51.358210+00:00 a3c6d79 DEBUG GET localhost/ 7 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
2023-09-06T14:16:51.672733+00:00 9da566b DEBUG GET localhost/ 9 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
2023-09-06T14:16:53.976604+00:00 7af6925 DEBUG GET localhost/ 8 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
2023-09-06T14:16:54.173788+00:00 ba7fda4 DEBUG GET localhost/ 11 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
2023-09-06T14:16:54.930687+00:00 18cf919 DEBUG GET localhost/ 10 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
2023-09-06T14:16:55.250928+00:00 9f082c1 DEBUG GET localhost/ 7 Closure->{closure}(22) Hello world! [] {"memory_usage":"4 MB","memory_peak_usage":"4 MB","file":"/var/www/slim_app/app/routes.php","ip":"172.19.0.1","referrer":null}
このとき、uidごとにログを抽出して分析したい場面があり、そのときに使用したシェルを備忘として残しました。
使用したスクリプト
ログが app.log というファイルの場合、下記のスクリプトを使用しました。
cat app.log \
| awk '{print $2}' \
| sort \
| uniq \
| xargs -t -P $(nproc) -I {} -n 1 sh -c "grep {} app.log > logs/{}.log"
実行結果
下記のファイルが出力されていれば成功です。
logs
├── 18cf919.log
├── 7af6925.log
├── 9da566b.log
├── 9f082c1.log
├── a3c6d79.log
├── ba7fda4.log
└── fd2b5fb.log
解説
このコードは、ログファイル (app.log
) から一意な値(重複を取り除いた値)を抽出し、それぞれの値に対して個別のログファイルを生成するシェルスクリプトの一部です。以下はコードのステップごとの説明です。
cat app.log
:
このコマンドは、app.log
ファイルの内容を標準出力に出力します。つまり、ファイルの内容を表示します。awk '{print $2}'
:awk
コマンドは、テキスト処理用の強力なツールで、指定されたパターンにマッチする行を処理できます。この場合、$2
は各行の2番目のフィールド(スペースで区切られた単語またはデータ)を抽出します。したがって、このステップではapp.log
ファイルの各行から2番目のフィールドを抽出して、それを標準出力に出力します。sort
:sort
コマンドは、行をアルファベット順にソートします。この場合、一意な値(2番目のフィールド)がソートされます。uniq
:uniq
コマンドは、連続する重複行を取り除いて一意な行のみを残します。このコードでは、一意な値だけが出力されます。xargs -t -P $(nproc) -I {} -n 1 sh -c "grep {} app.log > logs/{}.log"
:
この部分は、一意な値を処理し、それぞれの値に対してログファイルを生成する部分です。以下は各オプションとコマンドの説明です:
-t
: 実行するコマンドを表示します。-P $(nproc)
: 同時に実行するプロセスの数を、システムのCPUコア数 (nproc
コマンドで取得) に設定します。-I {}
:{}
というプレースホルダを指定します。このプレースホルダは後で一意な値に置き換えられます。-n 1
: 各コマンドを1回だけ実行します。sh -c "grep {} app.log > logs/{}.log"
: このコマンドは、grep
コマンドを使用して、一意な値(プレースホルダ{}
に置き換えられる)をapp.log
ファイルから検索し、それを個別のログファイル (logs/{}.log
) に保存します。
したがって、このコードは app.log
ファイルから一意な値を取得し、それぞれの値に対して個別のログファイルを生成します。各ログファイルには、元のログファイルから一意な値に一致する行が含まれます。このプロセスは、複数のプロセスを使用して高速化され、システムのCPUコア数に応じて並列処理が行われます。
おわりに
今日は、bashを利用したテキストの抽出方法についてご紹介しました。
よっしー
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント