AWS S3 copia archivos y carpetas entre dos depósitos

112

He estado buscando una herramienta que me ayude a copiar el contenido de un depósito de AWS S3 en un segundo depósito de AWS S3 sin descargar el contenido primero en el sistema de archivos local.

Intenté usar la opción de copia de la consola de AWS S3, pero eso resultó en la falta de algunos archivos anidados.

Intenté usar la aplicación Transmit (por Panic). El comando duplicado descarga los archivos primero en el sistema local y luego los vuelve a cargar en el segundo depósito, lo cual es bastante ineficiente.

cnicolaou
fuente
Considere aumentar el recuento de solicitudes simultáneas aws configure set default.s3.max_concurrent_requests 200 Consulte esta publicación para obtener más detalles y opciones stackoverflow.com/questions/4663016/…
Balmipour

Respuestas:

175

Copiar entre depósitos de S3

AWS (recientemente) lanzó una interfaz de línea de comandos para copiar entre depósitos.

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

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

Esto copiará de un depósito de destino a otro depósito.

Consulte la documentación aquí: Documentación de la CLI de S3

Layke
fuente
Lo ejecuté desde EC2 y obtuve 80 MB copiados en aproximadamente 5 segundos.
Stew-au
1
Exactamente lo que necesitaba, ya que aws-sdk gem no tiene función para copiar o sincronizar un depósito completo a la vez. ¡Gracias!
odigity
A 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.
Lanza
@GiovanniBitliner El nombre del depósito que está utilizando es incorrecto. Está utilizando el prefijo incorrecto o utilizando la forma antigua de referirse al cubo. Verifique el nombre de su depósito exactamente en su consola de administración.
Layke
8
Tenga en cuenta que si es la primera vez que usa la herramienta cli, debe ejecutar 'aws configure' e ingresar sus credenciales
S ..
41

Un ejemplo simplificado usando la gema 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 desea realizar la copia entre diferentes depósitos, especifique el nombre del depósito de destino:

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

Ahora puede hacerlo desde la interfaz de administración de S3. Simplemente vaya a un cubo y seleccione todas sus carpetas actions->copy. Luego muévete a tu nuevo cubo actions->paste.

KDEx
fuente
4
¡Increíble! Se refiere a la interfaz web. A diferencia de la mayoría de los demás, podría hacer esto desde un iPad.
Jacob Foshee
2
Esto omite aleatoriamente objetos anidados en subcarpetas: 3 años después, ¡AWS todavía no puede corregir un error tan básico!
RunLoop
¿Es para las mismas regiones o para todas?
hakiko
1
¿Están estos problemas documentados en alguna parte por Amazon? @RunLoop
davetapley
1
@dukedave No lo sé y no he vuelto a probar en bastante tiempo, ya que recurrí a hacer la copia a través de la línea de comandos, ya que funcionó perfectamente.
RunLoop
8

Es posible con la gema aws-sdk reciente , consulte el ejemplo de código:

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})

más detalles: Cómo copiar archivos a través de depósitos usando la gema aws-s3

Anatoly
fuente
Gracias por mostrarnos cómo copiar entre servidores. Estoy intentando copiar del servidor de EE. UU. Al servidor de Singapur.
Arcolye
@Arcolye, ¿cómo es la latencia en AWS Singapur ahora? Fue lento e inconsistente hace un año.
Anatoly
7

Copiar entre depósitos en diferentes regiones

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

El comando anterior copia un archivo de un depósito en Europa (eu-west-1) a Japón (ap-noreste-1). Puede obtener el nombre del código para la región de su depósito con este comando:

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

Por cierto, usar Copiar y Pegar en la consola web de S3 es fácil, pero parece que se descarga desde el depósito de origen al navegador y luego se carga al depósito de destino. Usar "aws s3" fue mucho más rápido para mí.

Adam Gawne-Cain
fuente
6

He creado un ejecutable de Docker de la herramienta s3s3mirror . Una utilidad para copiar y reflejar de un bucket de AWS S3 a otro.

Es un subproceso que permite la COPIA en paralelo y es muy eficiente en la memoria, tiene éxito donde s3cmd falla por completo.

Uso:

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

Para obtener una lista completa de opciones, pruebe:

docker run pmoust/s3s3mirror 
Panagiotis Moustafellos
fuente
5

Me imagino que probablemente ya haya encontrado una buena solución, pero para otras personas que se encuentran con este problema (como lo hice yo recientemente), he creado una utilidad simple específicamente con el propósito de reflejar un bucket de S3 en otro en de una manera altamente concurrente, pero eficiente en CPU y memoria.

Está en github bajo una licencia de Apache aquí: https://github.com/cobbzilla/s3s3mirror

Cuando tiene un cucharón muy grande y busca el máximo rendimiento, puede valer la pena intentarlo.

Si decide probarlo, avíseme si tiene algún comentario.

cobbzilla
fuente
Tuve una gran experiencia con s3s3mirror. Pude configurarlo en un nodo EC2 m1.small y copiar 1,5 millones de objetos en aproximadamente 2 horas. La configuración fue un poco difícil, debido a mi desconocimiento de Maven y Java, pero solo se necesitaron unos pocos comandos apt-get en Ubuntu para instalar todo. Una última nota: si (como yo) le preocupa ejecutar una secuencia de comandos desconocida en un depósito s3 grande e importante, cree un usuario especial con acceso de solo lectura en el depósito de copia desde y use esas credenciales. Cero posibilidad de eliminación accidental.
Micah
4

Si está en el shell y desea copiar varios archivos pero no todos los archivos: s3cmd cp --recursive s3: // BUCKET1 / OBJECT1 s3: // BUCKET2 [/ OBJECT2]

user1978008
fuente
3

Escribí un script que hace una copia de seguridad de un depósito de 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()

Yo uso esto en una tarea de rake (para una aplicación 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
Rosa Perrone
fuente
1

Escuché que hay un módulo de nodo para eso si estás en javascript: p

De los documentos de 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"
hurrymaplelad
fuente
Esto no es javascript, lo siento ... (sí, soy consciente de coffeescript y que puede usarlo, aún, no javascript)
Victor Schröder
1

Me informaron que también puede hacer esto usando s3distcp en un clúster EMR. Se supone que es más rápido para datos que contienen archivos grandes. Funciona lo suficientemente bien en pequeños conjuntos de datos, pero hubiera preferido otra solución dada la curva de aprendizaje que tomó configurar para tan pocos datos (nunca antes había trabajado con EMR).

Aquí hay un enlace de la documentación de AWS: http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/UsingEMR_s3distcp.html

Actualización: para el mismo conjunto de datos, s3s3mirror fue mucho más rápido que s3distcp o AWS cli. También es mucho más fácil de configurar.

Jorge el curioso
fuente
1

Para copiar de un bucket de S3 al mismo oa otro bucket de S3 sin descargarlo a local, es bastante sencillo. Utilice el siguiente comando de shell.

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

Esto copiará todos los archivos de la SourceFoldernamecarpeta del depósito de origen a la carpeta del depósito de destino TargetFoldername. En el código anterior, reemplace AccessKey, SecurityKeyy ExternalBucketcon sus valores correspondientes.

Sarath Avanavu
fuente
¿Qué es hdfs?
Anthony Kong
1

de AWS cli https://aws.amazon.com/cli/ podría hacer

aws s3 ls - Esto enumerará todos los cubos de S3

aws cp --recursive s3://<source bucket> s3://<destination bucket> - Esto copiará los archivos de un depósito a otro.

Nota * Muy útil al crear depósitos de replicación entre regiones. Al hacer lo anterior, se realiza un seguimiento de todos sus archivos y se propaga una actualización del archivo de la región de origen al depósito replicado. Todo menos las eliminaciones de archivos se sincroniza.

Para CRR, asegúrese de tener habilitado el control de versiones en los depósitos.

vredrav
fuente
0

¿Qué tal el aws s3 synccomando cli? aws s3 sync s3: // depósito1 / s3: // depósito2 /


fuente
0

Como ha explicado Neel Bhaat en este blog , hay muchas herramientas diferentes que se pueden utilizar para este propósito. Algunos son proporcionados por AWS, donde la mayoría son herramientas de terceros. Todas estas herramientas requieren que guarde la clave y el secreto de su cuenta de AWS en la propia herramienta. Tenga mucho cuidado al usar herramientas de terceros, ya que las credenciales en las que ahorra pueden costarle todo su valor y dejarlo muerto.

Por lo tanto, siempre recomiendo usar la AWS CLI para este propósito. Simplemente puede instalar esto desde este enlace . A continuación, ejecute el siguiente comando y guarde su clave, valores secretos en AWS CLI.

aws configure

Y use el siguiente comando para sincronizar su AWS S3 Bucket con su máquina local. (La máquina local debe tener AWS CLI instalada)

aws s3 sync <source> <destination>

Ejemplos:

1) Para AWS S3 a almacenamiento local

aws s3 sync <S3Uri> <LocalPath>

2) Del almacenamiento local a AWS S3

aws s3 sync <LocalPath> <S3Uri>

3) De un bucket de AWS s3 a otro bucket

aws s3 sync <S3Uri> <S3Uri> 
Keet Sugathadasa
fuente
0

La mejor forma de copiar el bucket de S3 es mediante la AWS CLI .

Implica estos 3 pasos:

  1. Instalación de AWS CLI en su servidor.
**https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html**
  1. Si está copiando depósitos entre dos cuentas de AWS, debe adjuntar la política correcta a cada depósito.

  2. Después de esto, use este comando para copiar de un depósito a otro.

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

Los detalles del paso 2 y el paso 3 se dan en este enlace:

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

Shubham Upadhyay
fuente