Подтвердить что ты не робот

Как удалить веером с версией в 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, но он делает ссылку на версии, отличную от собственной. Есть ли способ сделать это, не используя веб-интерфейс, который займет навсегда и требует, чтобы я оставил свой ноутбук?

4b9b3361

Ответ 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), поэтому вот тот, который вдохновлен ими, но идет немного глубже.

Как описано в разделе Работа с маркерами удаления, перед удалением версионного блока все его версии должны быть полностью удалены, что является двухэтапным процессом:

  1. "удалить" все объекты версии в корзине, что помечает их как удален, но фактически не удаляет их
  2. завершить удаление, удалив все объекты маркера удаления

Вот чистое решение 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+, если кто-то может сообщить, что это было бы здорово.