wake-up-neo.com

Wie lösche ich einen versionierten Bucket in AWS S3 über die CLI?

Ich habe beide versucht s3cmd:

$ s3cmd -r -f -v del s3://my-versioned-bucket/

Und die AWS CLI:

$ aws s3 rm s3://my-versioned-bucket/ --recursive

Beide Befehle fügen S3 jedoch einfach DELETE Marker hinzu. Der Befehl zum Entfernen eines Buckets funktioniert ebenfalls nicht (über die 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.

Ok, wie? Es gibt keine Informationen in deren Dokumentation dafür. S3Cmd sagt, es sei ein 'voll funktionsfähiges' S3-Befehlszeilentool, aber es macht kein Verweis auf Versionen anders als sein eigenes. Gibt es eine Möglichkeit, dies ohne Verwendung der Weboberfläche zu tun, was ewig dauern wird und erfordert, dass ich meinen Laptop eingeschaltet lasse?

49
NobleUplift

Eine Möglichkeit besteht darin, die Versionen zu durchlaufen und sie zu löschen. Ein bisschen knifflig in der CLI, aber wie Sie bereits erwähnt haben, wäre das einfacher:

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!");

Bei Bedarf können Sie Anrufe auch aus Effizienzgründen stapelweise löschen.

4
faermanj

Ich bin auf die gleiche Einschränkung der AWS-CLI gestoßen. Ich fand die einfachste Lösung darin, Python und boto :

#!/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()

In einer früheren Version dieser Antwort wurde boto verwendet, aber diese Lösung hatte Leistungsprobleme mit einer großen Anzahl von Schlüsseln, wie Chuckles hervorhob.

36
Abe Voelker

Verwenden von boto3 Es ist noch einfacher als mit der vorgeschlagenen boto Lösung, alle Objektversionen in einem S3-Bucket zu löschen:

#!/usr/bin/env python
import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('your-bucket-name')
bucket.object_versions.all().delete()

Funktioniert auch für sehr große Mengen von Objektversionen, obwohl dies in diesem Fall einige Zeit dauern kann.

17
Dunedan

Sie können alle Objekte im versionierten s3-Bucket löschen. Aber ich weiß nicht, wie ich bestimmte Objekte löschen soll.

$ aws s3api delete-objects \
      --bucket <value> \
      --delete "$(aws s3api list-object-versions \
      --bucket <value> | \
      jq '{Objects: [.Versions[] | {Key:.Key, VersionId : .VersionId}], Quiet: false}')"

Alternativ ohne 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}}')"
11
Cheers

Hier ist ein Einzeiler, den Sie einfach ausschneiden und in die Befehlszeile einfügen können, um alle Versionen und Markierungen zu löschen (es sind aws-Tools erforderlich, ersetzen Sie Ihr Bucket-Name-Backup durch Ihren Bucket-Namen).

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;

dann könnten Sie verwenden:

aws s3 rb s3://bucket-name --force

5
Nitin

Ich stieß auf Probleme mit Abes Lösung als list_buckets Generator wird verwendet, um eine massive Liste mit dem Namen all_keys und ich verbrachten eine Stunde, ohne dass es jemals abgeschlossen wurde. Dieser Tweak scheint für mich besser zu funktionieren, ich hatte fast eine Million Objekte in meinem Eimer und zähle!

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!

Hoffentlich hilft dies allen anderen, die diesem S3-Albtraum begegnen!

4
chuckwired
  1. Zum Löschen bestimmter Objekte mithilfe des JQ-Filters.
  2. Möglicherweise müssen Sie die 'DeleteMarker' und nicht nur die 'Versionen' bereinigen.
  3. Verwenden von $() anstelle von `` können Sie Variablen für Bucket-Name und Schlüsselwert einbetten.
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}')"
4
Tiger peng

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://}"

Z.B. empty_bucket.sh --bucket foo

Dadurch werden alle Objektversionen und Markierungen in einem Bucket in Stapeln von 1000 gelöscht. Anschließend kann der Bucket mit aws s3 rb s3://foo Gelöscht werden.

Benötigt bash, awscli und jq.

0
user2402169

Die mit Abstand einfachste Methode, die ich gefunden habe, ist die Verwendung dieses CLI-Tools s3wipe. Es wird als Docker-Container bereitgestellt, sodass Sie es folgendermaßen verwenden können:

$ 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`

Beispiel

Hier ist ein Beispiel, in dem ich alle versionierten Objekte in einem Bucket lösche und dann den Bucket lösche:

$ 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

Wie es funktioniert

Hier gibt es einiges zu entpacken, aber das Obige bewirkt Folgendes:

  • docker run -it --rm mikelorant/s3wipe - läuft s3wipe Container interaktiv und löscht ihn nach jeder Ausführung
  • --id & --key - Übergabe unseres Zugangsschlüssels und unserer Zugangs-ID
  • aws configure get default.aws_access_key_id - ruft unsere Schlüssel-ID ab
  • aws configure get default.aws_secret_access_key - ruft unser Schlüsselgeheimnis ab
  • --path s3://bw-tf-backends-aws-example-logs - Bucket, den wir löschen möchten
  • --delbucket - löscht den geleerten Eimer

Verweise

0
slm

Dieses Bash-Skript finden Sie hier: https://Gist.github.com/weavenet/f40b09847ac17dd99d16

arbeitete wie es für mich ist.

Ich habe das Skript als: delete_all_versions.sh gespeichert und dann einfach ausgeführt:

./delete_all_versions.sh my_foobar_bucket

und das hat einwandfrei funktioniert.

Benötigte nicht python oder Boto oder irgendetwas.

0
Mamun

Diese beiden Bash-Zeilen reichen aus, um das Löschen des Buckets zu ermöglichen!

1: Objekte löschen aws s3api delete-objects --bucket ${buckettoempty} --delete "$(aws s3api list-object-versions --bucket ${buckettoempty} --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"

2: Markierungen löschen aws s3api delete-objects --bucket ${buckettoempty} --delete "$(aws s3api list-object-versions --bucket ${buckettoempty} --query='{Objects: DeleteMarkers[].{Key:Key,VersionId:VersionId}}')"

0
Alexandre Hamon