Можно ли скопировать все файлы из одной корзины S3 в другую с помощью s3cmd? - PullRequest
74 голосов
/ 04 марта 2011

Я очень доволен s3cmd, но есть одна проблема: как скопировать все файлы из одной корзины S3 в другую?Это вообще возможно?

РЕДАКТИРОВАТЬ: Я нашел способ копировать файлы между корзинами, используя Python с 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

Синхронизация почти так же проста, как и копирование.Для ключей доступны поля для ETag, размера и последнего изменения.

Может быть, это поможет и другим.

Ответы [ 11 ]

88 голосов
/ 19 марта 2013

s3cmd sync s3://from/this/bucket/ s3://to/this/bucket/

Для доступных опций, пожалуйста, используйте: $s3cmd --help

41 голосов
/ 10 мая 2014

AWS CLI, кажется, отлично справляется со своей задачей и имеет преимущество в качестве официально поддерживаемого инструмента.

aws s3 sync s3://mybucket s3://backup-mybucket

http://docs.aws.amazon.com/cli/latest/reference/s3/sync.html

29 голосов
/ 06 декабря 2013

Ответ с наибольшим количеством голосов, как я пишу, таков:

s3cmd sync s3://from/this/bucket s3://to/this/bucket

Это полезный ответ. Но иногда синхронизация - это не то, что вам нужно (она удаляет файлы и т. Д.). Мне потребовалось много времени, чтобы найти альтернативу без сценариев, чтобы просто скопировать несколько файлов между корзинами. (Хорошо, в показанном ниже случае это не между сегментами. Это не между папками, но одинаково хорошо работает между сегментами.)

# Slightly verbose, slightly unintuitive, very useful:
s3cmd cp --recursive --exclude=* --include=file_prefix* s3://semarchy-inc/source1/ s3://semarchy-inc/target/

Объяснение вышеуказанной команды:

  • - рекурсивный
    На мой взгляд, мое требование не является рекурсивным. Я просто хочу несколько файлов. Но рекурсивный в этом контексте просто говорит s3cmd cp обрабатывать несколько файлов. Отлично.
  • –exclude
    Это странный способ думать о проблеме. Начните с рекурсивного выбора всех файлов. Далее исключите все файлы. Подожди, что?
  • - включите
    Теперь мы говорим. Укажите префикс файла (или суффикс или любой другой шаблон), который вы хотите включить.
    s3://sourceBucket/ s3://targetBucket/
    Эта часть достаточно понятна. Хотя технически это, кажется, нарушает документированный пример из справки s3cmd, который указывает, что должен быть указан исходный объект:
    s3cmd cp s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]
8 голосов
/ 30 марта 2016

Вы также можете использовать веб-интерфейс для этого:

  1. Перейти к исходной корзине в веб-интерфейсе.
  2. Отметить файлы, которые вы хотите скопировать (используйте shift ищелчок мышью, чтобы отметить несколько).
  3. Нажмите Действия-> Копировать.
  4. Перейдите в область назначения.
  5. Нажмите Действия-> Вставить.

Вот и все.

8 голосов
/ 19 декабря 2012

Мне нужно было скопировать очень большое ведро, поэтому я адаптировал код в вопросе в многопоточную версию и поместил его на GitHub.

https://github.com/paultuckey/s3-bucket-to-bucket-copy-py

3 голосов
/ 16 декабря 2015

Код mdahlman не работал для меня, но эта команда копирует все файлы в bucket1 в новую папку (команда также создает эту новую папку) в bucket 2.

cp --recursive --include=file_prefix* s3://bucket1/ s3://bucket2/new_folder_name/
3 голосов
/ 06 февраля 2013

Это на самом деле возможно.Это сработало для меня:

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)
2 голосов
/ 14 сентября 2012

Я написал скрипт для резервного копирования корзины 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()

Я использую это в задаче rake (для приложения 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
2 голосов
/ 14 августа 2012

Спасибо - я использую слегка измененную версию, где я копирую только файлы, которые не существуют или имеют другой размер, и проверяю место назначения, если ключ существует в источнике.Я нашел это немного быстрее для подготовки тестовой среды:

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
1 голос
/ 06 марта 2014

Вы также можете использовать s3funnel, который использует многопоточность:

https://github.com/neelakanta/s3funnel

пример (без указания ключа доступа или параметров секретного ключа):

s3funnel source-bucket-name list | s3funnel dest-bucket-name copy --source-bucket source-bucket-name --threads = 10

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...