Amazon S3の各バケット毎の合計容量・オブジェクト数を集計し、取得するAWS CLIを用いたシェルスクリプト(バッチ処理プログラム) ~バケット名を指定した検索、バケット名からリージョンを自動判定、バケットサイズ・ファイル数をリアルタイムで計算~

AWS,AWS CLI,EC2,Programming,S3,Shell Script

AWSにおいてAmazon S3は単純なファイル保存のストレージだけではなく、バックアップ、ウェブホスティング、バッチ処理・ビッグデータの中間データの保存など様々な用途に使用され、AWSを用いたシステムの核に位置づけられることも多くあると思います。

そのようなデータソースの中心ともなるAmazon S3ですが、保存できるオブジェクト容量、オブジェクト数に制限はないため、注意していないとバッチ処理等で大量のデータが保存されている状況も考えられます。

特にAmazon S3は保存データ容量に対する従量課金制なので保存するデータ容量が多ければ多いほど費用がかかります。

Amazon S3に保存されているバケット毎ののオブジェクト容量、オブジェクト数を知る方法は大きく分けて下記の2つの方法があります。

  • CloudWatchのメトリクスであるS3ストレージメトリクスのBucketSizeBytes、NumberOfObjectsを参照する。
  • AWS CLIでS3のバケット配下のオブジェクトに対して再帰的に容量と数を集計する。

ただ、CloudWatchのメトリクスは自動的に集計してくれるというメリットの一方で1日に1回の集計結果しか表示されないというデメリットがあるため、リアルタイムで容量やオブジェクト数を知りたい場合は使用できません。

今回はシステムやバッチ処理等でリアルタイムにS3バケット毎の容量・オブジェクト数が知りたい場合に使えるAWS CLIでS3のバケット配下のオブジェクトに対して再帰的に容量と数を集計するシェルスクリプト(バッチ処理プログラム)を備忘録として記載します。

Amazon S3の各バケット毎の合計容量・オブジェクト数を集計し、取得するAWS CLIを用いたシェルスクリプト(バッチ処理プログラム) ~バケット名を指定した検索、バケット名からリージョンを自動判定、バケットサイズ・ファイル数をリアルタイムで計算

基本方針としてはバケット名一覧を全て取得し、検索キーワードが引数にあれば、それを条件にバケットを絞込み、対象のバケットに対してAWS CLIでバケット配下のオブジェクト容量・オブジェクト数を再帰的に集計するという流れです。

Amazon S3の各バケット毎の合計容量・オブジェクト数を集計し、取得するAWS CLIを用いたシェルスクリプト(バッチ処理プログラム)

処理の内容は基本方針と同じですが、AWS CLIでバケットの情報を取得する場合にEU系のリージョンではリージョン指定をする文字列が無いとエラーが発生する場合があるため、各S3バケット名からリージョン指定をする文字列を生成する関数を作成してAWS CLI実行時に付加しています。

[magtranetwork@localhost ~]# vim check_s3_total_objects_size.sh
#!/bin/bash

# S3バケット名からリージョンオプション文字列を作成する関数
# \`bucket_region ${BUCKET}\`
bucket_region () {
  REGION=`aws s3api get-bucket-location --output text --bucket ${1}`
  if [ "${REGION}" = "None" -o "${REGION}" = "" ]; then
    REGION_STR=""
  else
    REGION_STR="--region ${REGION}"
  fi
  echo ${REGION_STR}
}

#検索文字列を引数から取得する。
PREFIX=$1

if [ "${PREFIX}" = "" ]; then
  #検索文字列が指定されていない場合は全てのバケット名を取得する。
  BUCKETS=(`aws s3 ls s3:// | awk '{print $NF}' | sed -e 's/ //g'`)
else
  #検索文字列が指定されている場合は検索文字列でバケット名を検索し、該当するものを取得する。
  BUCKETS=(`aws s3 ls s3:// | awk '{print $NF}' | sed -e 's/ //g' | grep "^${PREFIX}$"`)
fi

#取得したバケット名配列が空の場合は処理を終了。
if [ "${BUCKETS}" = "" ]; then
  echo "Target Bucket is not exists in S3."
  exit 1
fi

#取得したバケット名配列からバケット名を繰り返し取得し処理をする。
for BUCKET in ${BUCKETS[@]}; do
  #バケット配下のオブジェクトの容量・数を再帰的(--recursive)に集計(--summarize)し、人間が読めるフォーマットで表示(--human-readable)する。
  INFO=`aws s3 \`bucket_region ${BUCKET}\` ls --recursive --human-readable --summarize s3://${BUCKET} | grep "Total" | sed -e 's/ //g' | tr '\n' ' '`
  echo "BucketName:${BUCKET} ${INFO}"
done

Amazon S3の各バケット毎の合計容量・オブジェクト数を集計し、取得するAWS CLIを用いたシェルスクリプト(バッチ処理プログラム)の実行例

上記のシェルスクリプト(バッチ処理プログラム)の実行は引数を指定しなければAWSアカウントに存在する全てのS3バケットに対して集計を行います。

S3バケットを絞り込む場合は引数に検索文字列を指定して実行します。

<全件表示する場合の例>

[magtranetwork@localhost ~]# chmod 755 check_s3_total_objects_size.sh
[magtranetwork@localhost ~]# ./check_s3_total_objects_size.sh
BucketName:your-bucket-name-01 TotalObjects:12161 TotalSize:3.9GiB
BucketName:your-bucket-name-02 TotalObjects:12953 TotalSize:3.9GiB
BucketName:your-bucket-name-03 TotalObjects:47 TotalSize:141.9KiB
BucketName:your-bucket-name-04 TotalObjects:42 TotalSize:2.3GiB
BucketName:your-bucket-name-05 TotalObjects:57 TotalSize:44.6GiB
BucketName:your-bucket-name-06 TotalObjects:162 TotalSize:60.2MiB
BucketName:your-bucket-name-07 TotalObjects:4 TotalSize:77.9KiB
BucketName:your-bucket-name-08 TotalObjects:66537 TotalSize:23.2GiB
BucketName:your-bucket-name-09 TotalObjects:2 TotalSize:20.4KiB
BucketName:your-bucket-name-10 TotalObjects:4335 TotalSize:215.9MiB

<特定の文字列でバケットを検索する場合の例>

[magtranetwork@localhost ~]# chmod 755 check_s3_total_objects_size.sh
[magtranetwork@localhost ~]# ./check_s3_total_objects_size.sh your-bucket-name-05
BucketName:your-bucket-name-05 TotalObjects:57 TotalSize:44.6GiB

応用の可能性

今回はS3バケットの直下を再帰的に集計するものを作成しましたが、実際の集計を行っているAWS CLIコマンドで「s3://${BUCKET}/dir/」のようにサブフォルダを指定するとその配下を集計することができます。

複数ユーザーがS3バケットを使用していたり、バッチがS3バケット配下に自動的に中間ファイルを作成する場合など容量監視や通知を行いたい場合に今回の方法は活用できると思います。

Reference: Tech Blog citing related sources