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

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

我曾试图使用 AWS S3控制台复制选项,但这导致一些嵌套文件丢失。

我已经尝试使用传输应用程序(由恐慌)。复制命令首先将文件下载到本地系统,然后将它们上载回第二个 bucket,这样做效率很低。

172904 次浏览

查看下面的文档。我想这就是你要找的。 Http://docs.amazonwebservices.com/amazons3/latest/api/restobjectcopy.html

RightAws gem 的 S3Interface 具有执行上述操作的复制函数。

Http://rubydoc.info/gems/right_aws/3.0.0/rightaws/s3interface#copy-instance_method

可以使用最近的 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 跨桶复制文件

一个使用 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')

我编写了一个脚本来备份 S3 bucket: 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"

如果您在 shell 中,并且想要复制多个文件,但不是所有文件: S3cmd cp ——递归 s3://BUCKET1/ObjecCT1 s3://BUCKET2[/ObjecCT2]

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

它在 github 上使用 Apache 许可证: https://github.com/cobbzilla/s3s3mirror

当您有一个非常大的桶并且正在寻找最大的性能时,可能值得一试。

如果你决定尝试一下,请让我知道,如果你有任何反馈。

在 S3桶之间复制

AWS (最近)发布了一个命令行接口,用于在桶之间进行复制。

Http://aws.amazon.com/cli/

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

这个 收到从一个目标桶到另一个桶。

请参阅这里的文档: 中三课程学习领域文件

您现在可以从 S3管理界面执行此操作。只要进入一个桶选择您的所有文件夹 actions->copy。然后搬进你的新桶 actions->paste

我已经创建了一个 Docker 可执行文件S3s3镜子工具。 将 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

我被告知,您也可以在 EMR 集群上使用 s3distcp 来完成这项工作。对于包含大文件的数据,它应该更快。它在小型数据集上运行得很好——但是我更喜欢另一种解决方案,因为它需要为这么小的数据建立学习曲线(我以前从未使用过 EMR)。

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

更新: 对于相同的数据集,s3s3Mirror 比 s3distcp 或 AWS cli 快得多。安装起来也容易多了。

在不同区域的桶之间复制

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

上面的命令将一个文件从欧洲的 bucket (eu-west-1)复制到日本(ap-east-1)。您可以通过以下命令获得 bucket 区域的代码名:

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

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

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

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

这将把源 bucket 的 SourceFoldername文件夹中的所有文件复制到目标 bucket 的 TargetFoldername文件夹中。在以上代码中,请用相应的值替换 AccessKeySecurityKeyExternalBucket

aws s3 sync cli 命令怎么样。 Aws s3 sync s3://bucket et1/s3://bucket et2/

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

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

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

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

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

正如 Neel Bhaat 在这个 博客中所解释的,有许多不同的工具可以用于这个目的。一些是 AWS 提供的,其中大多数是第三方工具。所有这些工具都要求您将 AWS 帐户密钥和机密保存在工具本身中。在使用第三方工具时要非常小心,因为您保存的凭证可能会花费您、您的全部价值并导致您死亡。

因此,我总是建议为此目的使用 AWS CLI。您可以简单地从 这个链接安装它。接下来,运行以下命令并在 AWS CLI 中保存密钥和保密值。

aws configure

并使用以下命令将 AWS S3 Bucket 与本地计算机同步。(本地计算机应该安装了 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>

复制 S3 bucket 的最佳方法是使用 AWS CLI

它包括以下三个步骤:

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

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

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

有关 第二步步骤3的详情,请参阅以下连结:

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

您可以编写一个 Java 应用程序-也许甚至是一个 GUI SWING 应用程序,使用 AWS Java API 复制对象见-

Https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/s3/src/main/java/com/example/s3/copyobject.java

添加 使用 S3批处理操作跨 AWS 帐户复制对象是因为这里还没有提到它。这是我目前正在尝试的方法,因为我有大约100万个对象需要移动到一个新的帐户,cp 和 sync 对我来说不起作用,因为一些令牌过期,我没有办法弄清楚它是什么令牌,因为我的一般访问令牌工作得很好。

从2020年开始,如果您使用 S3cmd,您可以使用以下命令将一个文件夹从 bucket et1复制到 bucket et2

s3cmd cp --recursive s3://bucket1/folder_name/ s3://bucket2/folder_name/

--recursive必须递归地复制文件夹中的所有内容,还要注意,必须在文件夹名称后面指定“/”,否则会失败。