J'ai essayé les deux s3cmd
:
$ s3cmd -r -f -v del s3://my-versioned-bucket/
Et l'AWS CLI:
$ aws s3 rm s3://my-versioned-bucket/ --recursive
Mais ces deux commandes ajoutent simplement des marqueurs DELETE
à S3. La commande de suppression d'un compartiment ne fonctionne pas non plus (à partir de l'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, comment? Il n'y a aucune information dans leur documentation pour cela. S3Cmd dit que c'est un outil de ligne de commande S3 "complet", mais il fait aucune référence aux versions autre que le sien. Existe-t-il un moyen de le faire sans utiliser l'interface Web, ce qui prendra une éternité et me demandera de garder mon ordinateur portable allumé?
Une façon de le faire consiste à parcourir les versions et à les supprimer. Un peu délicat sur la CLI, mais comme vous l'avez mentionné Java, ce serait plus simple:
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!");
Vous pouvez également supprimer des appels par lots pour plus d'efficacité si nécessaire.
J'ai rencontré la même limitation de l'AWS CLI. J'ai trouvé la solution la plus simple à utiliser Python et 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()
Une version précédente de cette réponse utilisait boto mais cette solution avait des problèmes de performances avec un grand nombre de clés comme l'a souligné Chuckles.
En utilisant boto3
c'est encore plus simple qu'avec la solution boto
proposée pour supprimer toutes les versions d'objets dans un bucket S3:
#!/usr/bin/env python
import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('your-bucket-name')
bucket.object_versions.all().delete()
Fonctionne également très bien pour de très grandes quantités de versions d'objet, bien que cela puisse prendre un certain temps dans ce cas.
Vous pouvez supprimer tous les objets du compartiment s3 versionné. Mais je ne sais pas comment supprimer des objets spécifiques.
$ aws s3api delete-objects \
--bucket <value> \
--delete "$(aws s3api list-object-versions \
--bucket <value> | \
jq '{Objects: [.Versions[] | {Key:.Key, VersionId : .VersionId}], Quiet: false}')"
Alternativement sans 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}}')"
Voici une ligne que vous pouvez simplement couper et coller dans la ligne de commande pour supprimer toutes les versions et supprimer les marqueurs (cela nécessite des outils aws, remplacez votre sauvegarde de nom de bucket par votre nom de bucket)
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;
alors vous pouvez utiliser:
aws s3 rb s3://bucket-name --force
J'ai rencontré des problèmes avec la solution d'Abe comme list_buckets
le générateur est utilisé pour créer une liste massive appelée all_keys
et j'ai passé une heure sans jamais terminer. Ce Tweak semble mieux fonctionner pour moi, j'avais près d'un million d'objets dans mon seau et ça compte!
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!
Espérons que cela aide quiconque à rencontrer ce cauchemar S3!
$()
au lieu de ``
, vous pouvez incorporer des variables pour le nom de compartiment et la valeur-clé.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}')"
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
# $@ := 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://}"
Par exemple. empty_bucket.sh --bucket foo
Cela supprimera toutes les versions d'objet et supprimera les marqueurs dans un compartiment par lots de 1000. Ensuite, le compartiment peut être supprimé avec aws s3 rb s3://foo
.
Nécessite bash, awscli et jq.
De loin, la méthode la plus simple que j'ai trouvée consiste à utiliser cet outil CLI, s3wipe
. Il est fourni sous forme de conteneur Docker afin que vous puissiez l'utiliser comme ceci:
$ 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`
Voici un exemple où je supprime tous les objets versionnés dans un compartiment, puis je supprime le compartiment:
$ 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
[2019-02-20@03:39:16] INFO: Deleting from bucket: bw-tf-backends-aws-example-logs, path: None
[2019-02-20@03:39:16] INFO: Getting subdirs to feed to list threads
[2019-02-20@03:39:18] INFO: Done deleting keys
[2019-02-20@03:39:18] INFO: Bucket is empty. Attempting to remove bucket
Il y a un peu à déballer ici mais ce qui précède fait ce qui suit:
docker run -it --rm mikelorant/s3wipe
- exécute s3wipe
conteneur interactivement et le supprime après chaque exécution--id
& --key
- transmission de notre clé d'accès et de notre identifiant d'accèsaws configure get default.aws_access_key_id
- récupère notre identifiant de cléaws configure get default.aws_secret_access_key
- récupère notre clé secrète--path s3://bw-tf-backends-aws-example-logs
- compartiment que nous voulons supprimer--delbucket
- supprime le compartiment une fois vidéCe script bash se trouve ici: https://Gist.github.com/weavenet/f40b09847ac17dd99d16
a fonctionné tel quel pour moi.
J'ai enregistré le script sous: delete_all_versions.sh, puis j'ai simplement exécuté:
./delete_all_versions.sh my_foobar_bucket
et cela a fonctionné sans faille.
N'a pas eu besoin de python ou boto ou quoi que ce soit.