S3cmdにはかなり満足していますが、1つの問題があります。1つのS3バケットから別のバケットにすべてのファイルをコピーする方法ですか?それも可能ですか?
編集:Python with 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、サイズ、およびキーに使用可能な最終変更のフィールドがあります。
これは他の人にも役立つかもしれません。
s3cmd sync s3://from/this/bucket/ s3://to/this/bucket/
利用可能なオプションについては、次を使用してください:$s3cmd --help
AWS CLIは完璧に仕事をしているようで、公式にサポートされているツールであるというボーナスがあります。
aws s3 sync s3://mybucket s3://backup-mybucket
http://docs.aws.Amazon.com/cli/latest/reference/s3/sync.html
私がこれを書いているとき、最も賛成である答えはこれです:
s3cmd sync s3://from/this/bucket s3://to/this/bucket
役に立つ答えです。ただし、同期は必要なものではない場合があります(ファイルの削除など)。バケット間で複数のファイルを単純にコピーするこの非スクリプトの代替案を見つけるのに長い時間がかかりました。 (OK、以下に示す場合は、バケット間ではありません。実際にはフォルダ間ではありませんが、バケット間でも同様に機能します。)
# Slightly verbose, slightly unintuitive, very useful:
s3cmd cp --recursive --exclude=* --include=file_prefix* s3://semarchy-inc/source1/ s3://semarchy-inc/target/
上記のコマンドの説明:
s3://sourceBucket/ s3://targetBucket/
s3cmd cp s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]
Webインターフェースを使用してこれを行うこともできます。
それでおしまい。
非常に大きなバケットをコピーする必要があったため、問題のコードをマルチスレッドバージョンに適合させ、GitHubに配置しました。
実際に可能です。これは私のために働いた:
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)
mdahlmanのコードは機能しませんでしたが、このコマンドはバケット1のすべてのファイルをバケット2の新しいフォルダー(コマンドもこの新しいフォルダーを作成します)にコピーします。
cp --recursive --include=file_prefix* s3://bucket1/ s3://bucket2/new_folder_name/
ありがとう-存在しないか異なるサイズのファイルのみをコピーし、ソースにキーが存在するかどうかをチェックする、わずかに変更されたバージョンを使用します。テスト環境を準備するために、これが少し速くなったことがわかりました。
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
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 __=='__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
マルチスレッドを使用するs3funnelも使用できます。
https://github.com/neelakanta/s3funnel
例(表示されているアクセスキーまたはシークレットキーパラメータなし):
s3funnel source-bucket-nameリスト| s3funnel dest-bucket-name copy --source-bucket source-bucket-name --threads = 10
s3cmdはプレフィックスまたはワイルドカードのみでcpしませんが、「s3cmd ls sourceBucket」およびawkを使用して動作をスクリプト化して、オブジェクト名を抽出できます。次に、「s3cmd cp sourceBucket/name destBucket」を使用して、リスト内の各オブジェクト名をコピーします。
私はこれらのバッチファイルをWindowsのDOSボックスで使用します。
s3list.bat
s3cmd ls %1 | gawk "/s3/{ print \"\\"\"\"substr($0,index($0,\"s3://\"))\"\\"\"\"; }"
s3copy.bat
@for /F "delims=" %%s in ('s3list %1') do @s3cmd cp %%s %2