Je suis assez satisfait de s3cmd, mais il y a un problème: comment copier tous les fichiers d'un compartiment S3 vers un autre? Est-ce même possible?
EDIT: J'ai trouvé un moyen de copier des fichiers entre des compartiments en utilisant Python avec boto:
from boto.s3.connection import S3Connection
def copyBucket(srcBucketName, dstBucketName, maxKeys = 100):
conn = S3Connection(awsAccessKey, awsSecretKey)
srcBucket = conn.get_bucket(srcBucketName);
dstBucket = conn.get_bucket(dstBucketName);
resultMarker = ''
while True:
keys = srcBucket.get_all_keys(max_keys = maxKeys, marker = resultMarker)
for k in keys:
print 'Copying ' + k.key + ' from ' + srcBucketName + ' to ' + dstBucketName
t0 = time.clock()
dstBucket.copy_key(k.key, srcBucketName, k.key)
print time.clock() - t0, ' seconds'
if len(keys) < maxKeys:
print 'Done'
break
resultMarker = keys[maxKeys - 1].key
La synchronisation est presque aussi simple que la copie. Il existe des champs pour ETag, la taille et la dernière modification disponibles pour les clés.
Peut-être que cela aide aussi les autres.
s3cmd sync s3://from/this/bucket/ s3://to/this/bucket/
Pour les options disponibles, veuillez utiliser: $s3cmd --help
L'AWS CLI semble parfaitement faire le travail et a l'avantage d'être un outil officiellement pris en charge.
aws s3 sync s3://mybucket s3://backup-mybucket
http://docs.aws.Amazon.com/cli/latest/reference/s3/sync.html
La réponse avec le plus de votes au moment où j'écris ceci est celle-ci:
s3cmd sync s3://from/this/bucket s3://to/this/bucket
C'est une réponse utile. Mais parfois, la synchronisation n'est pas ce dont vous avez besoin (elle supprime les fichiers, etc.). Il m'a fallu beaucoup de temps pour trouver cette alternative sans script pour copier simplement plusieurs fichiers entre des compartiments. (OK, dans le cas ci-dessous, ce n'est pas entre des compartiments. C'est entre des dossiers pas vraiment, mais cela fonctionne aussi bien entre des compartiments.)
# Slightly verbose, slightly unintuitive, very useful:
s3cmd cp --recursive --exclude=* --include=file_prefix* s3://semarchy-inc/source1/ s3://semarchy-inc/target/
Explication de la commande ci-dessus:
s3://sourceBucket/ s3://targetBucket/
s3cmd cp s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]
Vous pouvez également utiliser l'interface Web pour ce faire:
C'est ça.
J'avais besoin de copier un très grand compartiment, j'ai donc adapté le code de la question dans une version multithread et l'ai mis sur GitHub.
C'est en fait possible. Cela a fonctionné pour moi:
import boto
AWS_ACCESS_KEY = 'Your access key'
AWS_SECRET_KEY = 'Your secret key'
conn = boto.s3.connection.S3Connection(AWS_ACCESS_KEY, AWS_SECRET_KEY)
bucket = boto.s3.bucket.Bucket(conn, SRC_BUCKET_NAME)
for item in bucket:
# Note: here you can put also a path inside the DEST_BUCKET_NAME,
# if you want your item to be stored inside a folder, like this:
# bucket.copy(DEST_BUCKET_NAME, '%s/%s' % (folder_name, item.key))
bucket.copy(DEST_BUCKET_NAME, item.key)
le code de mdahlman n'a pas fonctionné pour moi, mais cette commande copie tous les fichiers du bucket1 dans un nouveau dossier (la commande crée également ce nouveau dossier) dans le bucket 2.
cp --recursive --include=file_prefix* s3://bucket1/ s3://bucket2/new_folder_name/
Merci - J'utilise une version légèrement modifiée, où je copie uniquement les fichiers qui n'existent pas ou qui sont d'une taille différente, et vérifie la destination si la clé existe dans la source. J'ai trouvé cela un peu plus rapide pour préparer l'environnement de test:
def botoSyncPath(path):
"""
Sync keys in specified path from source bucket to target bucket.
"""
try:
conn = S3Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
srcBucket = conn.get_bucket(AWS_SRC_BUCKET)
destBucket = conn.get_bucket(AWS_DEST_BUCKET)
for key in srcBucket.list(path):
destKey = destBucket.get_key(key.name)
if not destKey or destKey.size != key.size:
key.copy(AWS_DEST_BUCKET, key.name)
for key in destBucket.list(path):
srcKey = srcBucket.get_key(key.name)
if not srcKey:
key.delete()
except:
return False
return True
J'ai écrit un script qui sauvegarde un compartiment S3: https://github.com/roseperrone/aws-backup-rake-task
#!/usr/bin/env python
from boto.s3.connection import S3Connection
import re
import datetime
import sys
import time
def main():
s3_ID = sys.argv[1]
s3_key = sys.argv[2]
src_bucket_name = sys.argv[3]
num_backup_buckets = sys.argv[4]
connection = S3Connection(s3_ID, s3_key)
delete_oldest_backup_buckets(connection, num_backup_buckets)
backup(connection, src_bucket_name)
def delete_oldest_backup_buckets(connection, num_backup_buckets):
"""Deletes the oldest backup buckets such that only the newest NUM_BACKUP_BUCKETS - 1 buckets remain."""
buckets = connection.get_all_buckets() # returns a list of bucket objects
num_buckets = len(buckets)
backup_bucket_names = []
for bucket in buckets:
if (re.search('backup-' + r'\d{4}-\d{2}-\d{2}' , bucket.name)):
backup_bucket_names.append(bucket.name)
backup_bucket_names.sort(key=lambda x: datetime.datetime.strptime(x[len('backup-'):17], '%Y-%m-%d').date())
# The buckets are sorted latest to earliest, so we want to keep the last NUM_BACKUP_BUCKETS - 1
delete = len(backup_bucket_names) - (int(num_backup_buckets) - 1)
if delete <= 0:
return
for i in range(0, delete):
print 'Deleting the backup bucket, ' + backup_bucket_names[i]
connection.delete_bucket(backup_bucket_names[i])
def backup(connection, src_bucket_name):
now = datetime.datetime.now()
# the month and day must be zero-filled
new_backup_bucket_name = 'backup-' + str('%02d' % now.year) + '-' + str('%02d' % now.month) + '-' + str(now.day);
print "Creating new bucket " + new_backup_bucket_name
new_backup_bucket = connection.create_bucket(new_backup_bucket_name)
copy_bucket(src_bucket_name, new_backup_bucket_name, connection)
def copy_bucket(src_bucket_name, dst_bucket_name, connection, maximum_keys = 100):
src_bucket = connection.get_bucket(src_bucket_name);
dst_bucket = connection.get_bucket(dst_bucket_name);
result_marker = ''
while True:
keys = src_bucket.get_all_keys(max_keys = maximum_keys, marker = result_marker)
for k in keys:
print 'Copying ' + k.key + ' from ' + src_bucket_name + ' to ' + dst_bucket_name
t0 = time.clock()
dst_bucket.copy_key(k.key, src_bucket_name, k.key)
print time.clock() - t0, ' seconds'
if len(keys) < maximum_keys:
print 'Done backing up.'
break
result_marker = keys[maximum_keys - 1].key
if __=='__main__':main()
J'utilise ceci dans une tâche de râteau (pour une application Rails):
desc "Back up a file onto S3"
task :backup do
S3ID = "*****"
S3KEY = "*****"
SRCBUCKET = "primary-mzgd"
NUM_BACKUP_BUCKETS = 2
Dir.chdir("#{Rails.root}/lib/tasks")
system "./do_backup.py #{S3ID} #{S3KEY} #{SRCBUCKET} #{NUM_BACKUP_BUCKETS}"
end
Vous pouvez également utiliser s3funnel qui utilise le multithread:
https://github.com/neelakanta/s3funnel
exemple (sans les paramètres de clé d'accès ou de clé secrète affichés):
s3funnel source-bucket-name list | s3funnel dest-bucket-name copy --source-bucket source-bucket-name --threads = 10
s3cmd ne sera pas cp avec seulement des préfixes ou des caractères génériques mais vous pouvez scripter le comportement avec 's3cmd ls sourceBucket', et awk pour extraire le nom de l'objet. Utilisez ensuite 's3cmd cp sourceBucket/name destBucket' pour copier chaque nom d'objet dans la liste.
J'utilise ces fichiers batch dans une boîte DOS sous Windows:
s3list.bat
s3cmd ls %1 | gawk "/s3/{ print \"\\"\"\"substr($0,index($0,\"s3://\"))\"\\"\"\"; }"
s3copy.bat
@for /F "delims=" %%s in ('s3list %1') do @s3cmd cp %%s %2