はじめに
バージョニングが有効なS3のオブジェクトはVersionsとDeleteMarkersの両方を削除しないと、
S3上からデータを完全に削除することができません。
また、AWSコンソール上で作成したフォルダはコンソール上からは削除できなかったり、少々ハマりどころがあります。
そのため、一括削除用のシェルスクリプトを作成しました。
(追記:AWS CLIの出力結果がJSON形式で、Nodeで対応した方が楽そうだったので勉強がてらNodeでも対応してみました。)
作成したシェル
echo 開始!
# バケット名
S3_BUCKET_NAME="バケット名"
# 削除対象をキーで絞り込み ※S3のフォルダパス
S3_OBJECT_KEY="test_dir/"
# Versionsの行数
versionsRows=1
# DeleteMarkersの行数
deleteMarkersRows=1
# key名のリスト
keys=()
# バージョンIDのリスト
versionIds=()
# Versionsの情報を取得
for i in $(
aws s3api list-object-versions --bucket ${S3_BUCKET_NAME} \
--query "Versions[?contains(Key,'${S3_OBJECT_KEY}')].{Key:Key, id:VersionId}" --output text
);
do
if [ $((${versionsRows} % 2)) = 1 ]; then
# 奇数
keys+=(${i})
else
# 偶数
versionIds+=(${i})
fi
let versionsRows++
done
# DeleteMarkersの情報を取得
for i in $(
aws s3api list-object-versions --bucket ${S3_BUCKET_NAME} \
--prefix ${S3_OBJECT_KEY} \
--query "DeleteMarkers[?contains(Key,'${S3_OBJECT_KEY}')].{Key:Key, id:VersionId}" --output text
);
do
if [ $((${deleteMarkersRows} % 2)) = 1 ]; then
# 奇数
keys+=(${i})
else
# 偶数
versionIds+=(${i})
fi
let deleteMarkersRows++
done
# VersionsとDeleteMarkersの削除処理
count=0
for key in ${keys[@]}; do
echo ${key}
echo ${versionIds[count]}
# 1件ずつkeyとversionIdを指定して削除する
aws s3api delete-object --bucket ${S3_BUCKET_NAME} \
--key ${key} --version-id ${versionIds[count]}
let count++
done
echo 終了
S3_BUCKET_NAME
とS3_OBJECT_KEY
を任意の値に置き換えてご使用ください。
(※S3_OBJECT_KEY
を空にするとバケット内のすべてのオブジェクトが消えるのでご注意ください。)
実行
sh delete-s3-object.sh
Nodeで処理する
const { execSync } = require('child_process')
const S3_BUCKET_NAME = "バケット名"
const S3_OBJECT_KEY = "S3のフォルダパス"
const stdout = execSync(
`aws s3api list-object-versions \
--bucket '${S3_BUCKET_NAME}' \
--prefix '${S3_OBJECT_KEY}'`,
{ maxBuffer: 2048 * 1024 } // デフォルトの1024 * 1024 からバッファ上限を増やす
)
const results = stdout.toString()
if (!results) {
console.log("ファイルが見つかりません")
return
}
// 出力結果の文字列をJSONに変換
const jsonData = JSON.parse(results)
if (jsonData.Versions && jsonData.Versions.length) {
console.log("Versionsの削除")
jsonData.Versions.forEach(version => {
const stdout = execSync(
`aws s3api delete-object --bucket '${S3_BUCKET_NAME}' \
--key '${version.Key}' --version-id ${version.VersionId}`
)
console.log(stdout.toString())
})
}
if (jsonData.DeleteMarkers && jsonData.DeleteMarkers.length) {
console.log("DeleteMarkersの削除")
jsonData.DeleteMarkers.forEach(deleteMarker => {
const stdout = execSync(
`aws s3api delete-object --bucket '${S3_BUCKET_NAME}' \
--key '${deleteMarker.Key}' --version-id ${deleteMarker.VersionId}`
)
console.log(stdout.toString())
})
}
実行
node delete-s3-object.js
補足
調べたところ、他にも同じようなことをされている方がすでにいらっしゃいました。
私自身、シェルやLinuxコマンドについて精通している訳ではないので、他の方々の記事も参考にしていただければと思います。
以上、少しでも参考になれば幸いです。
バージョニングを有効にしたS3で、オブジェクトを一気に削除したい
【AWS】CLIからバージョニングされたS3バケットを削除する方法
シェルコマンドを実行する方法(child_process)