バージョニングが有効化された 大量のAmazon S3 バケットをシェルスクリプトで一撃削除してみた

大量のS3バケットを手動で削除するのはめんどくさい…シェルスクリプトで一撃削除しましょう。
2023.04.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

投稿後にシェルスクリプトを修正しました。お手数ですが、こちらのブログをご参考ください。

手動での削除はめんどくさい。

こんにちは!AWS事業本部のおつまみです!

S3バケットを一撃で削除したいなぁと思ったことはありますか?私はあります。
つい先日CloudFomationでS3バケットを量産しすぎて、気づいたら同じプレフィックスのS3バケットを25個も作成してしまっていました。

通常S3バケットをマネージメントコンソールで削除する場合、以下の4ステップを踏む必要があります。

  • 削除対象のバケットを選択し、「空にする」を選択する。
  • 「完全に削除」を入力する。
  • 削除対象のバケットを選択し、「削除」を選択する。
  • バケット名を入力する。

これを25個全部で実施するのは、かなりめんどくさいですね。
そこでは今回はAWS CLIを使ったシェルスクリプトを使い、バージョニングが有効化された Amazon S3 バケットを一撃で削除したいと思います。

このブログで伝えたいこと

  • バージョニングが有効化された Amazon S3 バケットはaws s3 rmコマンドだけでは完全にオブジェクトを削除できない。
  • 旧バージョンのファイル削除には、s3api delete-objectsを使用する必要がある。
  • シェルスクリプトで効率化するのはいいね。

バージョニングが有効化された Amazon S3 バケットを削除するシェルスクリプト

作成したシェルスクリプトを記載します。

deleteS3.sh

#!/usr/bin/bash

bucket_name="$1"

# Abort the process if there is no argument
if [ $# != 1 ]; then
    echo "Please enter an argument."
    exit 1
fi

# Get the list of buckets to be deleted
backet_list=`aws s3api list-buckets | \
    jq -r ".Buckets[].Name" | \
    grep ${bucket_name} `

# There is no target bucket
if [ -z "${backet_list}" ]; then
    echo "There was no target bucket."
    exit 0
fi

# Confirm that you want to delete the bucket
echo "${backet_list}"
while true; do
    read -p "Do you want to delete this buckets? (y/n)" yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) exit 0;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo "Start deleting the bucket."

# Delete the bucket
echo "${backet_list}" | while read backet_name
do
    echo "Deleting ${backet_name} ..."
    aws s3api delete-objects --bucket $backet_name --delete "$(aws s3api list-object-versions --bucket $backet_name | jq '.Versions + .DeleteMarkers | {Objects: map({Key, VersionId}), Quiet: true}')"
    aws s3 rb s3://$backet_name --force
done

echo "done"

こちらのシェルスクリプト、ほぼ先人(のんピさん)が作成されたものを流用させていただきました。ありがとうございました。

処理のフローものんピさんの上記ブログより引用しています。

  • 引数として文字列を受け取る
    • 引数が1つじゃない = 正しいフォーマットではない場合は異常終了する
  • aws s3 api list-bucketsjqgrepで、引数として受け取った文字列がマッチするS3バケット名を取得する
    • マッチしたS3バケットが何もなければ正常終了する
  • マッチしたS3バケットの一覧を出力し、処理を続けるのか入力を受け付ける
    • 削除するのであればyesで、次の処理に進む
    • 削除しないのであれば、noで、正常終了する
    • yesもしくはno以外の文字列が入力された場合は、繰り返し確認する
  • マッチしたS3バケットを順に削除する

修正箇所

修正箇所はハイライトがかかっている一行のみになります。

deleteS3.sh

#!/usr/bin/bash

bucket_name="$1"

# Abort the process if there is no argument
if [ $# != 1 ]; then
    echo "Please enter an argument."
    exit 1
fi

# Get the list of buckets to be deleted
backet_list=`aws s3api list-buckets | \
    jq -r ".Buckets[].Name" | \
    grep ${bucket_name} `

# There is no target bucket
if [ -z "${backet_list}" ]; then
    echo "There was no target bucket."
    exit 0
fi

# Confirm that you want to delete the bucket
echo "${backet_list}"
while true; do
    read -p "Do you want to delete this buckets? (y/n)" yn
    case $yn in
        [Yy]* ) break;;
        [Nn]* ) exit 0;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo "Start deleting the bucket."

# Delete the bucket
echo "${backet_list}" | while read backet_name
do
    echo "Deleting ${backet_name} ..."
    aws s3api delete-objects --bucket $backet_name --delete "$(aws s3api list-object-versions --bucket $backet_name | jq '.Versions + .DeleteMarkers | {Objects: map({Key, VersionId}), Quiet: true}')"
    aws s3 rb s3://$backet_name --force
done

echo "done"

aws s3 rb --forceだけでバケット削除できないの?

S3のバージョニングが有効になっている場合は旧バージョンのオブジェクトが削除されません。 バージョンニングが有効になっているオブジェクトで、実施をすると以下のようなエラーが発生します。

% aws s3 rb s3://hogehogebucket --force
remove_bucket failed: s3://hogehogebucket An error occurred (BucketNotEmpty) when calling the DeleteBucket operation: The bucket you tried to delete is not empty. You must delete all versions in the bucket.

そのため、バージョニングが有効になっている場合は旧バージョンのファイル削除をするs3api delete-objectsを使用する必要があります。

s3api delete-objectsについて

AWS S3のAPIの1つで、S3バケットから複数のオブジェクトを削除するために使用されます。

このAPIを使用すると、1つ以上のオブジェクトを指定して、S3バケットから旧バージョンのファイルを同時に削除することができます。

例えば、以下のようなコマンドを使用して、S3バケットから複数のオブジェクトを削除することができます。

aws s3api delete-objects --bucket <bucket-name> --delete file://<file-name>

ただしこの場合は--deleteで単一のファイル指定しかできません。 一括削除するためには旧バージョンや削除マーカー含めて全てのファイルが指定される必要があるため、別途aws s3api list-object-versionsコマンドで情報を取得します。

aws s3api delete-objects --bucket $backet_name --delete "$(aws s3api list-object-versions --bucket $backet_name | jq '.Versions + .DeleteMarkers | {Objects: map({Key, VersionId}), Quiet: true}')"

今回スクリプトに追加したコマンドは、またもや先人(いわささん)が作成されたものをほぼ流用させていただきました。ありがとうございました。

実施してみた

Cloudshellから実行してみました。ログは以下のようになりました。

[cloudshell-user@ip-10-4-69-232 ~]$ sh deleteS3.sh windows-server-2022-for
windows-server-2022-for-bas-imagebuilderlogbucket-12atzebtnae4f
windows-server-2022-for-bas-imagebuilderlogbucket-15qm07xbr961i
windows-server-2022-for-bas-imagebuilderlogbucket-15snqjt7pi8oe
windows-server-2022-for-bas-imagebuilderlogbucket-16u71ylzfp2i9
windows-server-2022-for-bas-imagebuilderlogbucket-19ty6pde0v3ik
windows-server-2022-for-bas-imagebuilderlogbucket-1a1ag5kygpue1
windows-server-2022-for-bas-imagebuilderlogbucket-1e1n8ioaj85dj
windows-server-2022-for-bas-imagebuilderlogbucket-1gw6vbvs3wep3
windows-server-2022-for-bas-imagebuilderlogbucket-1gwzwhf0kkey3
windows-server-2022-for-bas-imagebuilderlogbucket-1hk8xxjnyxyi2
windows-server-2022-for-bas-imagebuilderlogbucket-1k32jqtegk6nx
windows-server-2022-for-bas-imagebuilderlogbucket-1k5nlwubosnpl
windows-server-2022-for-bas-imagebuilderlogbucket-1o4ypynussq9k
windows-server-2022-for-bas-imagebuilderlogbucket-1td1s7nv8zhjw
windows-server-2022-for-bas-imagebuilderlogbucket-5qydlxt62crq
windows-server-2022-for-bas-imagebuilderlogbucket-5wtvxi066tv4
windows-server-2022-for-bas-imagebuilderlogbucket-8t4qmpbyz54k
windows-server-2022-for-bas-imagebuilderlogbucket-9cbtopqiantx
windows-server-2022-for-bas-imagebuilderlogbucket-bvp59b5e21ap
windows-server-2022-for-bas-imagebuilderlogbucket-da3t5a952izb
windows-server-2022-for-bas-imagebuilderlogbucket-humufwi5zmml
windows-server-2022-for-bas-imagebuilderlogbucket-r6xar1fpj1b0
windows-server-2022-for-bas-imagebuilderlogbucket-rji4t70obgp2
windows-server-2022-for-bas-imagebuilderlogbucket-wck50cssdac
windows-server-2022-for-bas-imagebuilderlogbucket-y0vzjoep4iof
Do you want to delete this buckets? (y/n)y
Start deleting the bucket.
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-12atzebtnae4f ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-12atzebtnae4f
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-15qm07xbr961i ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-15qm07xbr961i
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-15snqjt7pi8oe ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-15snqjt7pi8oe
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-16u71ylzfp2i9 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-16u71ylzfp2i9
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-19ty6pde0v3ik ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-19ty6pde0v3ik
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1a1ag5kygpue1 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1a1ag5kygpue1
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1e1n8ioaj85dj ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1e1n8ioaj85dj
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1gw6vbvs3wep3 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1gw6vbvs3wep3
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1gwzwhf0kkey3 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1gwzwhf0kkey3
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1hk8xxjnyxyi2 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1hk8xxjnyxyi2
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1k32jqtegk6nx ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1k32jqtegk6nx
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1k5nlwubosnpl ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1k5nlwubosnpl
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1o4ypynussq9k ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1o4ypynussq9k
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-1td1s7nv8zhjw ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-1td1s7nv8zhjw
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-5qydlxt62crq ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-5qydlxt62crq
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-5wtvxi066tv4 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-5wtvxi066tv4
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-8t4qmpbyz54k ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-8t4qmpbyz54k
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-9cbtopqiantx ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-9cbtopqiantx
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-bvp59b5e21ap ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-bvp59b5e21ap
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-da3t5a952izb ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-da3t5a952izb
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-humufwi5zmml ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-humufwi5zmml
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-r6xar1fpj1b0 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-r6xar1fpj1b0
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-rji4t70obgp2 ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-rji4t70obgp2
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-wck50cssdac ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-wck50cssdac
Deleting windows-server-2022-for-bas-imagebuilderlogbucket-y0vzjoep4iof ...
remove_bucket: windows-server-2022-for-bas-imagebuilderlogbucket-y0vzjoep4iof
done

実行完了後再度マネージメントコンソールからS3バケットの一覧を確認すると、25個あったバケットが無事削除されていました!
ちなみに全て削除されるのに3分ほど時間がかかりました。

さいごに

今回はバージョニングが有効化された Amazon S3 バケットをAWS CLIで一撃削除する方法をご紹介しました。

先人のブログのおかげでかなり時間短縮することができました。ありがとうございます。

最後までお読みいただきありがとうございました!
どなたかのお役に立てれば幸いです。

以上、おつまみ(@AWS11077)でした!