aws s3 cpとsyncの違い | AWS CLI

AWS CLIのs3 cps3 syncの違いをまとめます。


はじめに

あるS3バケットのオブジェクトを別のS3バケットにコピーしようと思ったとき、2つのコマンドが頭に浮かびました。

s3 cps3 syncです。

雰囲気で分かったつもりになっていましたが、自分はまだ両者の違いを明確に説明できないことに気付きました。

今回は、この2つのコマンドの違いを調べます。


cpとsyncの違い

先に一言で両者の最も大きな違いを言うならば、

cpファイルをコピーするコマンド
syncディレクトリの更新差分をコピーする(同期する)コマンド

と言えるでしょう。


Descriptionを比較する

ではまず、両者のCLIドキュメントのDescriptionを比較します。

cp — AWS CLI 2.1.3 Command Reference

sync — AWS CLI 2.1.3 Command Reference

cp - Description:

Copies a local file or S3 object to another location locally or in S3.


sync - Description:

Syncs directories and S3 prefixes. Recursively copies new and updated files from the source directory to the destination. Only creates folders in the destination if they contain one or more files.

cpは単純に"オブジェクトのコピー"をするコマンドであるのに対し、syncでは"新規作成または更新されたファイル"について、"指定ディレクトリ以下を再帰的に"コピーする、ということが分かります ("ひとつ以上のファイルが含まれるフォルダのみを作成する"という挙動特性もあるようです)。

これらcpsyncの説明の違いは、ファイルを"コピー"するのか、ディレクトリを"同期(更新差分をコピー)"するのか、という違いとして直感的にも頷けるものでした。


コマンドオプションを比較する

次は、コマンドの実際の使い方を比較します。
具体的には、コマンドに用意されているオプションの差異を調べてみます。

cpsyncのコマンドオプションは大半が同じものですが、いくつか異なるものがあります。

f:id:BioErrorLog:20201024205152p:plain
cpコマンドとsyncコマンドのオプション比較 (灰色: cpとsyncの両方にあるオプション、オレンジ: それぞれのコマンドで独自のオプション)

まず、syncコマンドに特有のオプションとしては、以下のものがあります。

  • [--size-only]
  • [--exact-timestamps]
  • [--delete]

[--size-only]オプションは、sync元のファイルが更新されたか否か(=データコピーを実行するか否か)、をファイルサイズのみで判定することを指定するオプションのようです。

Makes the size of each key the only criteria used to decide whether to sync from source to destination.


[--exact-timestamps]オプションは、sync元のファイルが更新されたか否かを、タイムスタンプの一致まで見るオプションのようです。

When syncing from S3 to local, same-sized items will be ignored only when the timestamps match exactly. The default behavior is to ignore same-sized items unless the local version is newer than the S3 version.


[--delete]オプションは、sync先にはあるけれどsync元にはないファイルを削除するオプションです。

Files that exist in the destination but not in the source are deleted during sync.


上記3つのsync特有のオプションはいずれも、ディレクトリの更新差分をコピーする、というsyncコマンドの機能に深く関与するものと言えるでしょう。


次は、cpコマンド特有のオプションを見ていきます。

  • [--expected-size ]
  • [--recursive]

[--expected-size <value>]は、S3へのアップロードサイズが50GBを超える場合に、マルチパートアップロードをエラーなく実行するために必要なオプションのようです。

This argument specifies the expected size of a stream in terms of bytes. Note that this argument is needed only when a stream is being uploaded to s3 and the size is larger than 50GB. Failure to include this argument under these conditions may result in a failed upload due to too many parts in upload.


[--recursive]は、指定したディレクトリ下の全てのファイルを再帰的にコピーするオプションです。

Command is performed on all files or objects under the specified directory or prefix.


cpコマンドはsyncオプションと違い、ファイルのコピーをデフォルト挙動としているため、ディレクトリ下を再帰的にコピーしたい場合は[--recursive]オプションを使うことになります。

これはcpsyncの挙動の違いを表す、象徴的なオプションと言えるでしょう。


コマンドの挙動を比較する

最後に、実際にcpコマンドとsyncコマンドを叩いて挙動を確認することで、両者の違いを実感したいと思います。

f:id:BioErrorLog:20201025102215p:plain
syncとcpを用いたS3バケット間ファイルコピー

まずは単純に、S3バケット間の複数ファイルコピーを行います。

syncでこれを行うには、以下のシンプルなコマンドを発行します。

$ aws s3 sync s3://cp-sync-source s3://sync-destination                                                                                                   
copy: s3://cp-sync-source/aaa.txt to s3://sync-destination/aaa.txt
copy: s3://cp-sync-source/bbb.txt to s3://sync-destination/bbb.txt


一方、cpでディレクトリ単位のコピーを行うには、前述の通り--recursiveオプションを付与する必要があります。

$ aws s3 cp s3://cp-sync-source s3://cp-destination --recursive
copy: s3://cp-sync-source/bbb.txt to s3://cp-destination/bbb.txt
copy: s3://cp-sync-source/aaa.txt to s3://cp-destination/aaa.txt


では次に、ディレクトリ更新差分に対する両者の挙動の違いを見ていきます。

f:id:BioErrorLog:20201025104115p:plain
ディレクトリ更新後のsyncとcpの違い(赤: 更新ファイル)

コピー元のS3バケットcp-sync-sourceのうち、bbb.txtを更新し、ccc.txtファイルを新規追加しました。

この状態で再びsyncを行うと、

$ aws s3 sync s3://cp-sync-source s3://sync-destination
copy: s3://cp-sync-source/bbb.txt to s3://sync-destination/bbb.txt
copy: s3://cp-sync-source/ccc.txt to s3://sync-destination/ccc.txt

コピーが実行されるのはbbb.txtccc.txtのみで、aaa.txtはコピーされません。

一方cpを実行すると、

$ aws s3 cp s3://cp-sync-source s3://cp-destination --recursive
copy: s3://cp-sync-source/bbb.txt to s3://cp-destination/bbb.txt  
copy: s3://cp-sync-source/aaa.txt to s3://cp-destination/aaa.txt  
copy: s3://cp-sync-source/ccc.txt to s3://cp-destination/ccc.txt  

ディレクトリの更新差分とは関係なく、全ファイルが再びコピーされます。


このように、

cpファイルをコピーするコマンド
syncディレクトリの更新差分をコピーする(同期する)コマンド

という違いが見て取れました。


おわりに

今回は、AWS CLIコマンドのcpsyncの違いを調べました。

大まかな挙動の違いは、文字通り"コピー"なのか"同期"なのか、というのと直感的に近しいものでした。

が、各オプションを比較してみると、同じものと違うものとでそれぞれのコマンドの想定用法が見えてきて勉強になりました。

分かった気になっていても、今一度調べてみると多くの発見があって面白いものです。


関連記事

S3バケットポリシーとIAMポリシーの関係を、同一アカウント・クロスアカウントそれぞれにおいて整理しました。 www.bioerrorlog.work


S3への特定オブジェクトのアップロードをトリガーに、CloudWatch Eventsを起動するやり方の備忘録を書きました。 www.bioerrorlog.work


AWS Amplify & GraphQLでのデータモデル (スキーマ) 設計例をまとめました。 www.bioerrorlog.work


参考

cp — AWS CLI 2.1.3 Command Reference

sync — AWS CLI 2.1.3 Command Reference

Uploading objects - Amazon Simple Storage Service

s3 streaming upload allocates 5-10x more mem than the multipart chunk size (oom risk) and fails to saturate net tx (inefficient) · Issue #2390 · aws/aws-cli · GitHub