AWS S3在两个存储桶之间复制文件和文件夹


112

我一直在寻找一种工具来帮助我将AWS S3存储桶的内容复制到第二个AWS S3存储桶,而无需先将内容下载到本地文件系统。

我尝试使用AWS S3控制台复制选项,但是导致某些嵌套文件丢失。

我试图使用“发送”应用程序(通过Panic)。复制命令首先将文件下载到本地系统,然后将它们上传回第二个存储桶,这效率很低。


考虑增加并发请求数。aws configure set default.s3.max_concurrent_requests 200 有关更多详细信息和选项,请参阅这篇文章stackoverflow.com/questions/4663016/…–
Balmipour

Answers:


175

在S3存储桶之间复制

AWS(就在最近)发布了一个命令行界面,用于在存储桶之间进行复制。

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

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

这将从一个目标存储桶复制到另一个存储桶。

请参阅此处的文档:S3 CLI文档


从EC2中运行它,并在大约5s的时间内复制了80MB。
Stew-au

1
正是我所需要的,因为aws-sdk gem没有立即复制或同步整个存储桶的功能。谢谢!
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.
Giovanni Bitliner 2014年

@GiovanniBitliner您使用的存储桶名称不正确。您使用了错误的前缀,或者使用了旧的引用存储桶的方式。完全在管理控制台中检查您的存储桶名称。
Layke 2014年

8
注意如果这是使用CLI工具,你需要运行“AWS配置”,然后输入你的creds你第一次
秒。

41

使用aws-sdk gem的简化示例:

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

如果要在不同存储桶之间执行复制,请指定目标存储桶名称:

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

41

现在,您可以从S3管理界面进行操作。只需进入一个存储桶,选择所有文件夹即可actions->copy。然后移到新的存储桶中actions->paste


4
太棒了!他指的是Web界面。与大多数其他设备不同,我可以通过iPad进行此操作。
Jacob Foshee 2014年

2
这会在子文件夹中随机留下嵌套对象-三年后,AWS仍然无法修复此类基本错误!
RunLoop '16

是同一地区还是全部?
hakiko

1
亚马逊在任何地方都记录了这些问题吗?@RunLoop
davetapley18年

1
@dukedave我不知道,并且很长一段时间都没有再次测试,因为我通过命令行进行复制非常有效。
RunLoop

8

最近的aws-sdk gem 有可能,请参见代码示例:

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

更多详细信息:如何使用aws-s3 gem在存储桶之间复制文件


感谢您展示如何跨服务器复制。我正在尝试从我们的服务器复制到新加坡服务器。
Arcolye

@Arcolye现在新加坡AWS的延迟如何?一年前,它很慢且不一致。
阿纳托利

7

在不同区域的存储桶之间复制

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

上面的命令将文件从欧洲(eu-west-1)的存储桶复制到日本(ap-northeast-1)。您可以使用以下命令获取存储区的代码名称:

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

顺便说一句,在S3 Web控制台中使用“复制和粘贴”很容易,但是它似乎是从源存储桶下载到浏览器,然后再上传到目标存储桶。对我而言,使用“ aws s3”要快得多。


6

我创建了一个泊坞可执行s3s3mirror工具。从AWS S3存储桶复制并镜像到另一个的实用程序。

它是线程化的,允许并行COPY和非常高效的内存,它在s3cmd完全失败的情况下成功。

用法:

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

有关选项的完整列表,请尝试:

docker run pmoust/s3s3mirror 


5

我以为您现在可能已经找到了一个好的解决方案,但是对于其他遇到此问题的人(就像我最近一样),我精心设计了一个简单的实用程序,专门用于将一个S3存储桶镜像到另一个S3存储桶。高度并发,但CPU和内存高效的方式。

在Apache许可下的github上:https : //github.com/cobbzilla/s3s3mirror

当您有一个很大的存储桶并寻求最佳性能时,可能值得尝试。

如果您决定尝试一下,如果您有任何反馈意见,请告诉我。


我在s3s3mirror方面有丰富的经验。我能够在m1.small EC2节点上进行设置,并在大约2个小时内复制了150万个对象。由于我不熟悉Maven和Java,因此安装过程有些困难,但是在Ubuntu上只需要执行几个apt-get命令即可安装所有组件。最后一点:如果(像我一样)担心在一个重要的大型s3存储桶上运行未知脚本,请创建一个特殊用户,该用户对“复制自”存储桶具有只读访问权限,并使用这些凭据。意外删除的机会为零。
米卡

4

如果您在外壳程序中并且要复制多个文件但不是所有文件,请执行以下操作:s3cmd cp --recursive s3:// BUCKET1 / OBJECT1 s3:// BUCKET2 [/ OBJECT2]


3

我写了一个脚本来备份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 = "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

1

我听说有一个节点模块,如果您喜欢javascript:p

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"

这不是javascript,抱歉...(是的,我知道coffeescript了,您仍然可以使用它而不是javascript)
VictorSchröder19年

1

我被告知您也可以在EMR群集上使用s3distcp来执行此操作。对于包含大文件的数据,它应该更快。它适用于少量数据集,但效果很好-但考虑到要为这么少的数据设置所需的学习曲线,我会更喜欢另一种解决方案(我以前从未使用过EMR)。

这是来自AWS文档的链接:http : //docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/UsingEMR_s3distcp.html

更新:对于相同的数据集,s3s3mirror比s3distcp或AWS cli快得多。设置起来也容易得多。


1

要从一个S3存储桶复制到相同或另一个S3存储桶而不下载到本地,这非常简单。使用以下shell命令。

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

这会将所有文件从源存储桶的SourceFoldername文件夹复制到目标存储桶的TargetFoldername文件夹。在上面的代码,请更换AccessKeySecurityKeyExternalBucket与相应的值。


什么hdfs
安东尼·孔

1

从AWS CLI https://aws.amazon.com/cli/你可以做

aws s3 ls -这将列出所有S3存储桶

aws cp --recursive s3://<source bucket> s3://<destination bucket> -这会将文件从一个存储桶复制到另一个存储桶

注意*在创建跨区域复制存储桶时非常有用,通过执行上述操作,可以跟踪所有文件,并且对源区域文件的更新将传播到复制的存储桶中。除文件删除以外的所有内容均已同步。

对于CRR,请确保在存储桶上启用了版本控制。


0

aws s3 synccli命令如何。aws s3同步s3:// bucket1 / s3:// bucket2 /


0

正如Neel Bhaat在此博客中解释的那样,有许多不同的工具可用于此目的。有些是由AWS提供的,其中大多数是第三方工具。所有这些工具都要求您在工具本身中保存您的AWS账户密钥和机密。使用第三方工具时要格外小心,因为您保存的凭据可能会花费您全部金钱,并使您丧命。

因此,我始终建议为此使用AWS CLI。您可以从此链接简单地安装它。接下来,运行以下命令并将您的密钥秘密值保存在AWS CLI中。

aws configure

并使用以下命令将您的AWS S3存储桶同步到本地计算机。(本地计算机应已安装AWS CLI)

aws s3 sync <source> <destination>

例子:

1)对于AWS S3到本地存储

aws s3 sync <S3Uri> <LocalPath>

2)从本地存储到AWS S3

aws s3 sync <LocalPath> <S3Uri>

3)从AWS s3存储桶到另一个存储桶

aws s3 sync <S3Uri> <S3Uri> 

0

复制S3存储桶的最佳方法是使用AWS CLI

它涉及以下三个步骤:

  1. 在服务器上安装AWS CLI。
**https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html**
  1. 如果要在两个AWS账户之间复制存储桶,则需要在每个存储桶中附加正确的策略。

  2. 之后,使用此命令从一个存储桶复制到另一个存储桶。

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

此链接中提供了步骤2步骤3的详细信息:

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.