Как удалить веером с версией в AWS S3 с помощью CLI?
Я пробовал как s3cmd
:
$ s3cmd -r -f -v del s3://my-versioned-bucket/
И AWI CLI:
$ aws s3 rm s3://my-versioned-bucket/ --recursive
Но обе эти команды просто добавляют маркеры DELETE
к S3. Команда для удаления ведра также не работает (из AWS CLI):
$ aws s3 rb s3://my-versioned-bucket/ --force
Cleaning up. Please wait...
Completed 1 part(s) with ... file(s) remaining
remove_bucket failed: s3://my-versioned-bucket/ A client error (BucketNotEmpty) occurred when calling the DeleteBucket operation: The bucket you tried to delete is not empty. You must delete all versions in the bucket.
Хорошо... как? Для этого нет информации в их документации. S3Cmd говорит, что это "полнофункциональный" инструмент командной строки S3, но он делает ссылку на версии, отличную от собственной. Есть ли способ сделать это, не используя веб-интерфейс, который займет навсегда и требует, чтобы я оставил свой ноутбук?
Ответы
Ответ 1
Один из способов сделать это - перебирать версии и удалять их. Немного сложно в CLI, но, как вы упомянули Java, это было бы более просто:
AmazonS3Client s3 = new AmazonS3Client();
String bucketName = "deleteversions-"+UUID.randomUUID();
//Creates Bucket
s3.createBucket(bucketName);
//Enable Versioning
BucketVersioningConfiguration configuration = new BucketVersioningConfiguration(ENABLED);
s3.setBucketVersioningConfiguration(new SetBucketVersioningConfigurationRequest(bucketName, configuration ));
//Puts versions
s3.putObject(bucketName, "some-key",new ByteArrayInputStream("some-bytes".getBytes()), null);
s3.putObject(bucketName, "some-key",new ByteArrayInputStream("other-bytes".getBytes()), null);
//Removes all versions
for ( S3VersionSummary version : S3Versions.inBucket(s3, bucketName) ) {
String key = version.getKey();
String versionId = version.getVersionId();
s3.deleteVersion(bucketName, key, versionId);
}
//Removes the bucket
s3.deleteBucket(bucketName);
System.out.println("Done!");
Вы также можете пакетно удалить вызовы для повышения эффективности, если это необходимо.
Ответ 2
Я столкнулся с тем же ограничением интерфейса командной строки AWS. Я нашел самое простое решение - использовать Python и boto3:
#!/usr/bin/env python
BUCKET = 'your-bucket-here'
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket(BUCKET)
bucket.object_versions.delete()
# if you want to delete the now-empty bucket as well, uncomment this line:
#bucket.delete()
Предыдущая версия этого ответа использовала boto, но это решение имело проблемы с производительностью из-за большого количества клавиш, как указал Чаклз.
Ответ 3
Используя boto3
, даже проще, чем с помощью предложенного решения boto
, удалить все версии объектов в корзине S3:
#!/usr/bin/env python
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('your-bucket-name')
bucket.object_versions.all().delete()
Хорошо работает и для очень большого количества версий объектов, хотя в этом случае это может занять некоторое время.
Ответ 4
Вы можете удалить все объекты в версионной корзине s3.
Но я не знаю, как удалять определенные объекты.
$ aws s3api delete-objects \
--bucket <value> \
--delete "$(aws s3api list-object-versions \
--bucket <value> | \
jq '{Objects: [.Versions[] | {Key:.Key, VersionId : .VersionId}], Quiet: false}')"
Альтернативно без jq
:
$ aws s3api delete-objects \
--bucket ${bucket_name} \
--delete "$(aws s3api list-object-versions \
--bucket "${bucket_name}" \
--output=json \
--query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"
Ответ 5
Вот один вкладыш, который вы можете просто вырезать и вставить в командную строку, чтобы удалить все версии и удалить маркеры (для этого требуются инструменты aws, замените yourbucket-name-backup на ваше имя корзины)
echo '#!/bin/bash' > deleteBucketScript.sh \
&& aws --output text s3api list-object-versions --bucket $BUCKET_TO_PERGE \
| grep -E "^VERSIONS" |\
awk '{print "aws s3api delete-object --bucket $BUCKET_TO_PERGE --key "$4" --version-id "$8";"}' >> \
deleteBucketScript.sh && . deleteBucketScript.sh; rm -f deleteBucketScript.sh; echo '#!/bin/bash' > \
deleteBucketScript.sh && aws --output text s3api list-object-versions --bucket $BUCKET_TO_PERGE \
| grep -E "^DELETEMARKERS" | grep -v "null" \
| awk '{print "aws s3api delete-object --bucket $BUCKET_TO_PERGE --key "$3" --version-id "$5";"}' >> \
deleteBucketScript.sh && . deleteBucketScript.sh; rm -f deleteBucketScript.sh;
тогда вы можете использовать:
aws s3 rb s3://bucket-name --force
Ответ 6
- Для удаления определенного объекта (ов), используя jq-фильтр.
- Вам может потребоваться очистка "DeleteMarkers" не только "Версии".
- Используя
$()
вместо ``
, вы можете вставлять переменные для bucket-name и key-value.
aws s3api delete-objects --bucket bucket-name --delete "$(aws s3api list-object-versions --bucket bucket-name | jq -M '{Objects: [.["Versions","DeleteMarkers"][]|select(.Key == "key-value")| {Key:.Key, VersionId : .VersionId}], Quiet: false}')"
Ответ 7
Я столкнулся с проблемами с Abe solution, поскольку генератор list_buckets
используется для создания массивного списка под названием all_keys
, и я провел час без его завершения, Кажется, эта настройка работает лучше для меня, у меня было около миллиона объектов в моем ковше и подсчета!
import boto
s3 = boto.connect_s3()
bucket = s3.get_bucket("your-bucket-name-here")
chunk_counter = 0 #this is simply a nice to have
keys = []
for key in bucket.list_versions():
keys.append(key)
if len(keys) > 1000:
bucket.delete_keys(keys)
chunk_counter += 1
keys = []
print("Another 1000 done.... {n} chunks so far".format(n=chunk_counter))
#bucket.delete() #as per usual uncomment if you're sure!
Надеюсь, это поможет кому-то еще столкнуться с этим кошмаром S3!
Ответ 8
Безусловно, самый простой метод, который я нашел, это использовать этот инструмент CLI, s3wipe
. Он предоставляется в качестве док-контейнера, поэтому вы можете использовать его следующим образом:
$ docker run -it --rm slmingol/s3wipe --help
usage: s3wipe [-h] --path PATH [--id ID] [--key KEY] [--dryrun] [--quiet]
[--batchsize BATCHSIZE] [--maxqueue MAXQUEUE]
[--maxthreads MAXTHREADS] [--delbucket] [--region REGION]
Recursively delete all keys in an S3 path
optional arguments:
-h, --help show this help message and exit
--path PATH S3 path to delete (e.g. s3://bucket/path)
--id ID Your AWS access key ID
--key KEY Your AWS secret access key
--dryrun Don't delete. Print what we would have deleted
--quiet Suprress all non-error output
--batchsize BATCHSIZE # of keys to batch delete (default 100)
--maxqueue MAXQUEUE Max size of deletion queue (default 10k)
--maxthreads MAXTHREADS Max number of threads (default 100)
--delbucket If S3 path is a bucket path, delete the bucket also
--region REGION Region of target S3 bucket. Default vaue 'us-
east-1'
ПримерExample
Вот пример, где я удаляю все версионные объекты в корзине, а затем удаляю корзину:
$ docker run -it --rm slmingol/s3wipe \
--id $(aws configure get default.aws_access_key_id) \
--key $(aws configure get default.aws_secret_access_key) \
--path s3://bw-tf-backends-aws-example-logs \
--delbucket
[[email protected]:39:16] INFO: Deleting from bucket: bw-tf-backends-aws-example-logs, path: None
[[email protected]:39:16] INFO: Getting subdirs to feed to list threads
[[email protected]:39:18] INFO: Done deleting keys
[[email protected]:39:18] INFO: Bucket is empty. Attempting to remove bucket
Как это работает
Там немного распаковать здесь, но выше делает следующее:
docker run -it --rm mikelorant/s3wipe
- интерактивно запускает контейнер s3wipe
и удаляет его после каждого выполнения
--id
& --key
- передача ключа доступа и идентификатора доступа в
aws configure get default.aws_access_key_id
- возвращает наш ключевой идентификатор
aws configure get default.aws_secret_access_key
- возвращает наш секретный ключ
--path s3://bw-tf-backends-aws-example-logs
- корзина, которую мы хотим удалить
--delbucket
- удаляет ведро после опустошения
Ссылки
Ответ 9
https://gist.github.com/wknapik/191619bfa650b8572115cd07197f3baf
#!/usr/bin/env bash
set -eEo pipefail
shopt -s inherit_errexit >/dev/null 2>&1 || true
if [[ ! "$#" -eq 2 || "$1" != --bucket ]]; then
echo -e "USAGE: $(basename "$0") --bucket <bucket>"
exit 2
fi
# [email protected] := bucket_name
empty_bucket() {
local -r bucket="${1:?}"
for object_type in Versions DeleteMarkers; do
local opt=() next_token=""
while [[ "$next_token" != null ]]; do
page="$(aws s3api list-object-versions --bucket "$bucket" --output json --max-items 1000 "${opt[@]}" \
--query="[{Objects: ${object_type}[].{Key:Key, VersionId:VersionId}}, NextToken]")"
objects="$(jq -r '.[0]' <<<"$page")"
next_token="$(jq -r '.[1]' <<<"$page")"
case "$(jq -r .Objects <<<"$objects")" in
'[]'|null) break;;
*) opt=(--starting-token "$next_token")
aws s3api delete-objects --bucket "$bucket" --delete "$objects";;
esac
done
done
}
empty_bucket "${2#s3://}"
Э.Г. empty_bucket.sh --bucket foo
Это удалит все версии объектов и удалит маркеры в корзине партиями по 1000. После этого корзина может быть удалена с помощью aws s3 rb s3://foo
.
Требуется bash, awscli и jq.
Ответ 10
Этот скрипт bash находится здесь: https://gist.github.com/weavenet/f40b09847ac17dd99d16
работал как у меня.
Я сохранил скрипт как: delete_all_versions.sh, а затем просто запустил:
./delete_all_versions.sh my_foobar_bucket
и это сработало без изъянов.
Не нужно Python или Бото или что-нибудь.
Ответ 11
Это работает для меня. Может быть, запуск более поздних версий чего-то и выше> 1000 наименований. запустил пару миллионов файлов сейчас. Однако он все еще не закончен через полдня и не имеет средств для проверки в AWS GUI =/
# Set bucket name to clearout
BUCKET = 'bucket-to-clear'
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket(BUCKET)
max_len = 1000 # max 1000 items at one req
chunk_counter = 0 # just to keep track
keys = [] # collect to delete
# clear files
def clearout():
global bucket
global chunk_counter
global keys
result = bucket.delete_objects(Delete=dict(Objects=keys))
if result["ResponseMetadata"]["HTTPStatusCode"] != 200:
print("Issue with response")
print(result)
chunk_counter += 1
keys = []
print(". {n} chunks so far".format(n=chunk_counter))
return
# start
for key in bucket.object_versions.all():
item = {'Key': key.object_key, 'VersionId': key.id}
keys.append(item)
if len(keys) >= max_len:
clearout()
# make sure last files are cleared as well
if len(keys) > 0:
clearout()
print("")
print("Done, {n} items deleted".format(n=chunk_counter*max_len))
#bucket.delete() #as per usual uncomment if you're sure!
Ответ 12
Для тех, кто использует несколько профилей через ~/.aws/config
import boto3
PROFILE = "my_profile"
BUCKET = "my_bucket"
session = boto3.Session(profile_name = PROFILE)
s3 = session.resource('s3')
bucket = s3.Bucket(BUCKET)
bucket.object_versions.delete()
Ответ 13
Я обнаружил, что другие ответы либо неполные, либо требуют установки внешних зависимостей (например, boto), поэтому вот тот, который вдохновлен ими, но идет немного глубже.
Как описано в разделе Работа с маркерами удаления, перед удалением версионного блока все его версии должны быть полностью удалены, что является двухэтапным процессом:
- "удалить" все объекты версии в корзине, что помечает их как
удален, но фактически не удаляет их
- завершить удаление, удалив все объекты маркера удаления
Вот чистое решение CLI, которое сработало для меня (вдохновлено другими ответами):
#!/usr/bin/env bash
bucket_name=...
del_s3_bucket_obj()
{
local bucket_name=$1
local obj_type=$2
local query="{Objects: $obj_type[].{Key:Key,VersionId:VersionId}}"
local s3_objects=$(aws s3api list-object-versions --bucket ${bucket_name} --output=json --query="$query")
if ! (echo $s3_objects | grep -q '"Objects": null'); then
aws s3api delete-objects --bucket "${bucket_name}" --delete "$s3_objects"
fi
}
del_s3_bucket_obj ${bucket_name} 'Versions'
del_s3_bucket_obj ${bucket_name} 'DeleteMarkers'
Как только это будет сделано, сработает следующее:
aws s3 rb "s3://${bucket_name}"
Не уверен, как это будет с объектами 1000+, если кто-то может сообщить, что это было бы здорово.