AWS CLIで複数ファイルに対してS3 Selectで検索する


環境

  • aws-cli 2.7.14

概要

S3に保存されているCloudFrontのログを検索したかったのですが
Athenaは導入されていなかったのでS3 Selectを使って検索をしました。

S3 Selectは1ファイルずつしか検索できないので、
AWS CLIをシェルに組み込んで複数ファイル検索できるようにしました。

手順

条件は以下とします。

  • S3バケット名は「target-bucket-name」
  • 「logs-dir」というディレクトリ内に「AABBCCDDEE123456.YYYY-MM-DD-HH.abcdefg・・・」形式でファイルが生成される。
  • aws cli用のprofileは「my-aws-profile」という名前で設定してある。

できあがったものはこちら。

# ①設定
PROFILE="my-aws-profile"
BUCKET="target-bucket-name"
PREFIX="logs-dir/AABBCCDDEE123456.2024-12-11"    # 左記例では2024年12月11日に出力された分を検索する。
QUERY="SELECT * FROM s3object s"                 # 左記例では全て出力しています。列を絞ったりWHERE句を入れたりしてください。

# ②オブジェクト(ファイル)の一覧取得
objects=`aws s3api list-objects --profile $PROFILE --bucket $BUCKET --prefix $PREFIX | jq`

# ③取得したオブジェクトの一覧に対して1件ずつ処理をする
for object in $(echo "$objects" | jq -c '.Contents[]'); do
  key=$(echo "$object" | jq -r '.Key')
  echo "$key"

  # ④検索結果出力
  aws s3api select-object-content --profile $PROFILE --bucket $BUCKET --key $key --expression "$QUERY" --expression-type SQL --input-serialization '{"CSV": {"FileHeaderInfo": "NONE", "FieldDelimiter": "\t"}, "CompressionType": "GZIP"}' --output-serialization '{"CSV": {"FieldDelimiter": ","}}' output-tmp.csv
  cat output-tmp.csv >> output.csv
done

rm -f output-tmp.csv

①設定

必要な情報を設定してください。

PREFIXは必要なファイルを絞れるように設定しないと。検索対象が無駄に増えるとお金がかかってしまいます。
料金については以下を参照。
https://aws.amazon.com/jp/s3/pricing/

QUERYについては以下も参照。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-select-sql-reference-select.html

②オブジェクト(ファイル)の一覧取得

AWS CLIを利用してS3のバケットおよびPrefixが一致するオブジェクトの一覧を取得します。
取得したjsonを解読するためjqコマンドも噛ませています。
※profile設定時にoutputをjsonにしてある。

③取得したオブジェクトの一覧に対して1件ずつ処理をする

オブジェクト(ファイル)の配列は「Contents」というキーで返ってくるので、
それを指定してforで回します。

④検索結果出力

S3 Selectのコマンド結果はファイルに出力するしかないので、
現在のオブジェクトの検索結果は一時ファイル(output-tmp.csv)に出力してから
最終ファイル(output.csv)に追記していくようにしています。

これで検索結果が出力されます。
あとは必要な情報をさらに絞るためにクエリを修正したりしていけば欲しい情報が取れるようになります。