AWS S3 copie des fichiers et des dossiers entre deux compartiments

112

Je suis à la recherche d'un outil pour m'aider à copier le contenu d'un compartiment AWS S3 dans un deuxième compartiment AWS S3 sans télécharger d'abord le contenu dans le système de fichiers local.

J'ai essayé d'utiliser l'option de copie de la console AWS S3, mais cela a entraîné l'absence de certains fichiers imbriqués.

J'ai essayé d'utiliser l'application Transmit (par Panic). La commande duplicate télécharge d'abord les fichiers sur le système local, puis les télécharge de nouveau dans le deuxième compartiment, ce qui est assez inefficace.

cnicolaou
la source
Envisagez d' augmenter votre nombre de requêtes simultanées aws configure set default.s3.max_concurrent_requests 200 Voir cet article pour plus de détails et d' options stackoverflow.com/questions/4663016/...
Balmipour

Réponses:

175

Copie entre les compartiments S3

AWS (tout récemment) a publié une interface de ligne de commande pour la copie entre les buckets.

http://aws.amazon.com/cli/

$ aws s3 sync s3://mybucket-src s3://mybucket-target --exclude *.tmp
..

Cela copiera d'un bucket cible vers un autre bucket.

Consultez la documentation ici: Documentation de la CLI S3

Layke
la source
Ran it from EC2 et 80 Mo copiés en 5 s environ.
Stew-au
1
Exactement ce dont j'avais besoin, car aws-sdk gem n'a pas de fonction pour copier ou synchroniser un bucket entier à la fois. Merci!
odigity
Il jette l'erreur suivanteA client error (PermanentRedirect) occurred when calling the ListObjects operation: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
Giovanni Bitliner
@GiovanniBitliner Le nom du compartiment que vous utilisez est incorrect. Soit vous utilisez le mauvais préfixe, soit vous utilisez l'ancienne façon de faire référence au bucket. Vérifiez exactement le nom de votre bucket dans votre console d'administration.
Layke
8
Notez que si c'est la première fois que vous utilisez l'outil cli, vous devez exécuter 'aws configure' et entrer vos creds
S ..
41

Un exemple simplifié utilisant le gem aws-sdk:

AWS.config(:access_key_id => '...', :secret_access_key => '...')
s3 = AWS::S3.new
s3.buckets['bucket-name'].objects['source-key'].copy_to('target-key')

Si vous souhaitez effectuer la copie entre différents buckets, spécifiez le nom du bucket cible:

s3.buckets['bucket-name'].objects['source-key'].copy_to('target-key', :bucket_name => 'target-bucket')
Trevor Rowe
la source
41

Vous pouvez maintenant le faire depuis l'interface d'administration S3. Allez dans un seul compartiment, sélectionnez tous vos dossiers actions->copy. Ensuite, passez à votre nouveau seau actions->paste.

KDEx
la source
4
Impressionnant! Il fait référence à l'interface Web. Contrairement à la plupart des autres, je pourrais le faire à partir d'un iPad.
Jacob Foshee
2
Cela laisse de côté les objets imbriqués dans les sous-dossiers au hasard - 3 ans plus tard et AWS ne peut toujours pas résoudre un bogue aussi basique!
RunLoop
est-ce pour les mêmes régions ou pour toutes?
hakiko
1
Ces problèmes sont-ils documentés n'importe où par Amazon? @RunLoop
davetapley
1
@dukedave Je ne sais pas et je n'ai pas testé à nouveau depuis un bon moment car j'ai recouru à la copie via la ligne de commande car cela fonctionnait parfaitement.
RunLoop
8

C'est possible avec la gemme aws-sdk récente , voir l'exemple de code:

require 'aws-sdk'

AWS.config(
  :access_key_id     => '***',
  :secret_access_key => '***',
  :max_retries       => 10
)

file     = 'test_file.rb'
bucket_0 = {:name => 'bucket_from', :endpoint => 's3-eu-west-1.amazonaws.com'}
bucket_1 = {:name => 'bucket_to',   :endpoint => 's3.amazonaws.com'}

s3_interface_from = AWS::S3.new(:s3_endpoint => bucket_0[:endpoint])
bucket_from       = s3_interface_from.buckets[bucket_0[:name]]
bucket_from.objects[file].write(open(file))

s3_interface_to   = AWS::S3.new(:s3_endpoint => bucket_1[:endpoint])
bucket_to         = s3_interface_to.buckets[bucket_1[:name]]
bucket_to.objects[file].copy_from(file, {:bucket => bucket_from})

plus de détails: Comment copier un fichier dans des buckets à l'aide de la gemme aws-s3

Anatoly
la source
Merci d'avoir montré comment copier sur les serveurs. J'essaye de copier du serveur de nous au serveur de singapour.
Arcolye
@Arcolye Quelle est la latence dans AWS Singapour maintenant? C'était lent et incohérent il y a un an.
Anatoly
7

Copier entre des buckets dans différentes régions

$ aws s3 cp s3://src_bucket/file  s3://dst_bucket/file --source-region eu-west-1 --region ap-northeast-1

La commande ci-dessus copie un fichier d'un compartiment en Europe (eu-west-1) vers le Japon (ap-Nord-Est-1). Vous pouvez obtenir le nom de code de la région de votre bucket avec cette commande:

$ aws s3api get-bucket-location --bucket my_bucket

À propos, il est facile d'utiliser Copier et Coller dans la console Web S3, mais il semble que le téléchargement du compartiment source dans le navigateur, puis le téléversement vers le compartiment de destination. Utiliser "aws s3" était beaucoup plus rapide pour moi.

Adam Gawne-Cain
la source
6

J'ai créé un exécutable Docker de l' outil s3s3mirror . Un utilitaire pour copier et mettre en miroir un compartiment AWS S3 vers un autre.

Il est threadé permettant une COPIE parallèle et très efficace en mémoire, il réussit là où s3cmd échoue complètement.

Usage:

docker run -e AWS_ACCESS_KEY_ID=FOO -e AWS_SECRET_ACCESS_KEY=BAR pmoust/s3s3mirror [OPTIONS] source_bucket[/prefix] dest_bucket[/prefix]

Pour une liste complète des options, essayez:

docker run pmoust/s3s3mirror 
Panagiotis Moustafellos
la source
5

J'imagine que vous avez probablement trouvé une bonne solution maintenant, mais pour d'autres qui rencontrent ce problème (comme je l'ai été récemment), j'ai conçu un utilitaire simple spécifiquement dans le but de mettre en miroir un compartiment S3 dans un autre dans une manière hautement simultanée, mais efficace en termes de CPU et de mémoire

C'est sur github sous une licence Apache ici: https://github.com/cobbzilla/s3s3mirror

Lorsque vous avez un très grand compartiment et que vous recherchez des performances maximales, cela vaut la peine d'essayer.

Si vous décidez d'essayer, faites-moi savoir si vous avez des commentaires.

Cobbzilla
la source
J'ai eu une super expérience avec s3s3mirror. J'ai pu l'installer sur un nœud m1.small EC2 et copier 1,5 million d'objets en environ 2 heures. La configuration était un peu difficile, en raison de ma méconnaissance de Maven et Java, mais il n'a fallu que quelques commandes apt-get sur Ubuntu pour tout installer. Une dernière note: si (comme moi) vous craignez d'exécuter un script inconnu sur un grand et important bucket s3, créez un utilisateur spécial avec un accès en lecture seule sur le bucket de copie et utilisez ces informations d'identification. Aucune chance de suppression accidentelle.
Micah
4

Si vous êtes dans le shell et que vous souhaitez copier plusieurs fichiers mais pas tous les fichiers: s3cmd cp --recursive s3: // BUCKET1 / OBJECT1 s3: // BUCKET2 [/ OBJECT2]

user1978008
la source
3

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  __name__ =='__main__':main()

J'utilise ceci dans une tâche de rake (pour une application Rails):

desc "Back up a file onto S3"
task :backup do
     S3ID = "AKIAJM3NRWC7STXWUWVQ"
     S3KEY = "0A5kuzV+E1dkaPjZxHQAezz1GlSddJd0iS5sNpry"
     SRCBUCKET = "primary-mzgd"
     NUM_BACKUP_BUCKETS = 2

     Dir.chdir("#{Rails.root}/lib/tasks")
     system "./do_backup.py #{S3ID} #{S3KEY} #{SRCBUCKET} #{NUM_BACKUP_BUCKETS}"
end
Rose Perrone
la source
1

J'entends qu'il y a un module de nœud pour cela si vous aimez javascript: p

À partir des documents knox-copy :

knoxCopy = require 'knox-copy'

client = knoxCopy.createClient
  key: '<api-key-here>'
  secret: '<secret-here>'
  bucket: 'backups'

client.copyBucket
  fromBucket: 'uploads'
  fromPrefix: '/nom-nom'
  toPrefix: "/upload_backups/#{new Date().toISOString()}"
  (err, count) ->
     console.log "Copied #{count} files"
dépêchez-vous
la source
Ce n'est pas du javascript, désolé ... (oui, je suis au courant de coffeescript et que vous pouvez l'utiliser, encore, pas de javascript)
Victor Schröder
1

J'ai été informé que vous pouvez également le faire en utilisant s3distcp sur un cluster EMR. Il est censé être plus rapide pour les données contenant de gros fichiers. Cela fonctionne assez bien sur de petits ensembles de données - mais j'aurais préféré une autre solution compte tenu de la courbe d'apprentissage qu'il a fallu pour configurer pour si peu de données (je n'ai jamais travaillé avec EMR auparavant).

Voici un lien de la documentation AWS: http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/UsingEMR_s3distcp.html

Mise à jour: pour le même ensemble de données, s3s3mirror était beaucoup plus rapide que s3distcp ou le cli AWS. Beaucoup plus facile à configurer aussi.

curious_george
la source
1

Pour copier d'un compartiment S3 vers le même ou un autre compartiment S3 sans téléchargement vers local, c'est assez simple. Utilisez la commande shell ci-dessous.

hdfs dfs -cp -f "s3://AccessKey:SecurityKey@ExternalBucket/SourceFoldername/*.*" "s3://AccessKey:SecurityKey@ExternalBucket/TargetFoldername"

Cela copiera tous les fichiers du SourceFoldernamedossier du bucket source vers le dossier du bucket cible TargetFoldername. Dans le code ci - dessus, s'il vous plaît remplacer AccessKey, SecurityKeyet ExternalBucketavec vos valeurs correspondantes.

Sarath Avanavu
la source
Qu'est-ce que c'est hdfs?
Anthony Kong le
1

depuis AWS cli https://aws.amazon.com/cli/ vous pouvez faire

aws s3 ls - Cela listera tous les seaux S3

aws cp --recursive s3://<source bucket> s3://<destination bucket> - Cela copiera les fichiers d'un compartiment à un autre

Remarque * Très utile lors de la création de compartiments de réplication interrégionale, en faisant ce qui précède, vos fichiers sont tous suivis et une mise à jour du fichier de la région source sera propagée vers le compartiment répliqué. Tout sauf les suppressions de fichiers sont synchronisés.

Pour CRR, assurez-vous que la gestion des versions est activée sur les buckets.

vredrav
la source
0

Que diriez-vous de la aws s3 synccommande cli. aws s3 sync s3: // bucket1 / s3: // bucket2 /


la source
0

Comme Neel Bhaat l'a expliqué dans ce blog , il existe de nombreux outils différents qui peuvent être utilisés à cette fin. Certains sont fournis par AWS, la plupart étant des outils tiers. Tous ces outils vous obligent à enregistrer votre clé de compte AWS et votre secret dans l'outil lui-même. Soyez très prudent lorsque vous utilisez des outils tiers, car les informations d'identification que vous enregistrez peuvent vous coûter la totalité de votre valeur et vous faire mourir.

Par conséquent, je recommande toujours d'utiliser l' AWS CLI à cette fin. Vous pouvez simplement l'installer à partir de ce lien . Ensuite, exécutez la commande suivante et enregistrez votre clé, vos valeurs secrètes dans AWS CLI.

aws configure

Et utilisez la commande suivante pour synchroniser votre compartiment AWS S3 avec votre machine locale. (L'AWS CLI doit être installée sur la machine locale)

aws s3 sync <source> <destination>

Exemples:

1) Pour AWS S3 vers le stockage local

aws s3 sync <S3Uri> <LocalPath>

2) Du stockage local à AWS S3

aws s3 sync <LocalPath> <S3Uri>

3) Du bucket AWS s3 vers un autre bucket

aws s3 sync <S3Uri> <S3Uri> 
Keet Sugathadasa
la source
0

La meilleure façon de copier le compartiment S3 consiste à utiliser l' AWS CLI .

Il implique ces 3 étapes:

  1. Installation de l'AWS CLI sur votre serveur.
**https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html**
  1. Si vous copiez des buckets entre deux comptes AWS, vous devez attacher la stratégie correcte à chaque bucket.

  2. Après cela, utilisez cette commande pour copier d'un compartiment à un autre.

aws s3 sync s3://sourcebucket s3://destinationbucket

Les détails des étapes 2 et 3 sont donnés dans ce lien:

https://aws.amazon.com/premiumsupport/knowledge-center/account-transfer-s3/

Shubham Upadhyay
la source