AWS S3在两个桶之间复制文件和文件夹
我一直在寻找一种工具来帮助我将S3存储桶的内容复制到第二个存储桶中,而无需将内容先下载到本地系统。
我已经尝试了AWS S3控制台复制选项,但导致一些嵌套的文件丢失。
我试图使用传输应用程序(恐慌),但重复命令复制文件首先到本地系统,然后回到第二个桶
在S3存储桶之间复制
AWS(就在最近)发布了一个用于在存储桶之间进行复制的命令行界面。
$ aws s3 sync s3://mybucket-src s3://mybucket-target --exclude *.tmp ..
这将从一个目标桶复制到另一个桶。
请参阅此处的文档: S3 CLI文档
使用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')
您现在可以从S3pipe理界面执行此操作。 只要进入一个桶select所有的文件夹操作actions->copy
。 然后进入新的存储桶操作actions->paste
。
最近的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跨桶复制文件
结帐下面的文件。 我想这就是你在找什么。 http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectCOPY.html
RightAws gem的S3Interface有一个复制function,可以完成上述function。
http://rubydoc.info/gems/right_aws/3.0.0/RightAws/S3Interface#copy-instance_method
我想现在你可能已经find了一个很好的解决scheme,但是对于遇到这个问题的其他人(就像我刚才那样),我已经制作了一个简单的工具,专门用于将一个S3存储桶镜像到另一个高度并发,但CPU和内存有效的方式。
它在github上的Apache许可证下: https : //github.com/cobbzilla/s3s3mirror
当你有一个非常大的桶,并寻求最大的性能,这可能是值得一试。
如果您决定尝试一下,请告诉我,如果您有任何反馈意见。
我已经创build了s3s3mirror工具的Docker可执行文件 。 从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
如果你在shell中,想复制多个文件但不是所有文件:s3cmd cp –recursive s3:// BUCKET1 / OBJECT1 s3:// BUCKET2 [/ OBJECT2]
在不同区域的桶之间进行复制
$ 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”对我来说要快得多。
我写了一个备份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
我听说有一个节点模块,如果你在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"
我被告知你也可以在EMR集群上使用s3distcp来做到这一点。 包含大文件的数据应该会更快。 它在小数据集上运行得很好 – 但是我会更喜欢另一种解决scheme,因为它只需要很less的数据(我从来没有用过EMR)。
以下是AWS文档的链接: http : //docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/UsingEMR_s3distcp.html
更新:对于相同的数据集,s3s3mirror比s3distcp或AWS cli快得多。 更容易设置。