【AWS】Amazon S3 ~ AWS CLI / aws s3 sync ~

■ はじめに

https://dk521123.hatenablog.com/entry/2017/04/01/235355

で、S3 の AWS CLI については扱ったが、
aws s3 sync がうまく扱えないので、深堀りしてみた。

ちゃんと理解しないとバグの原因になりうる。
(特に --delete オプション付けた時に、、、)

目次

【1】aws s3 sync
 1)構文
【2】オプション
 1)--include / --exclude
 2)--delete
 3)--size-only / --exact-timestamps
 4)--no-progress / --quiet / --only-show-errors
【3】使用上の注意
 1)--exact-timestamps を付けといた方がいい
 2)--include / --excludeは、後に指定する方を優先する
 3)--deleteオプション + --excludeオプションした際の指定の仕方

【1】aws s3 sync

* S3データを再帰的に同期する
* aws s3 cp では再帰的なコピーは「--recursive」が必要だが、
 sync はデフォルトで再帰的。

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html

より抜粋
~~~~~~~~~
Syncs directories and S3 prefixes. "Recursively" copies new ...
~~~~~~~~~

1)構文

# 「同期元」を基準に「同期先」を合わせる
aws s3 sync <同期元(s3 or local)> <同期先(s3 or local)> [--options]

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-sync
重要ポイント

この「同期元」「同期先」を意識しておくことが重要
(あくまで同期元が主)

【2】オプション

* 全てのオプションではないが、公式ドキュメントで日本語訳(機械翻訳)ででている

https://docs.aws.amazon.com/ja_jp/snowball/latest/developer-guide/using-adapter-cli.html

Options Explanations Memo
--dryrun ドライラン(実行しない) 手作業での復旧時や調査時に使えそう
--include ファイルやオブジェクトを同期に含める 詳細は「【2】オプション」の「1)--include / --exclude」を参照
--exclude ファイルやオブジェクトを同期から除外 詳細は「【2】オプション」の「1)--include / --exclude」を参照
--follow-symlinks / --no-follow-symlinks ローカルファイルシステムから Amazon S3にアップロードする場合にのみ、シンボリックリンク (symlinks) をたどる
--no-guess-mime-type MIMEタイプを推測せず、代わりにデフォルトのタイプを使用
--delete 同期元になく同期先にはあるファイルを削除 詳細は「【2】オプション」の「2)--delete」を参照
--size-only サイズが同じファイルは処理しない 詳細は「【2】オプション」の「3)--size-only / --exact-timestamps」を参照
--exact-timestamps タイムスタンプが一致したものは処理しない 詳細は「【2】オプション」の「3)--size-only / --exact-timestamps」を参照
--quiet 一切出力しない 詳細は「【2】オプション」の「4)--no-progress / --quiet / --only-show-errors」を参照
--only-show-errors エラーと警告だけを表示 詳細は「【2】オプション」の「4)--no-progress / --quiet / --only-show-errors」を参照
--no-progress 進捗状況だけを非表示にする 詳細は「【2】オプション」の「4)--no-progress / --quiet / --only-show-errors」を参照
--no-cli-pager 実行に限り一時的にページャー無効 https://dev.classmethod.jp/articles/tsnote-aws-cli-command-result-is-truncated/
--cli-auto-prompt 自動プロンプトモードをON
--no-cli-auto-prompt 自動プロンプトモードをOFF

1)--include / --exclude

[1] --include

* ファイルやオブジェクトを同期に含める

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html

より抜粋
~~~~~~~~~~~
--include (string)

Don’t exclude files or objects in the command that match the specified pattern.
指定されたパターンに一致するコマンド内のファイルやオブジェクトを除外しない。

See Use of Exclude and Include Filters for details.
詳細については、ExcludeフィルタとIncludeフィルタの使用を参照してください。
~~~~~~~~~~~

https://docs.aws.amazon.com/cli/latest/reference/s3/#use-of-exclude-and-include-filters

[2] --exclude

* ファイルやオブジェクトを同期から除外

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html

より抜粋
~~~~~~~~~~~
--exclude (string)

Exclude all files or objects from the command that matches the specified pattern.
指定されたパターンにマッチするすべてのファイルまたはオブジェクトを
コマンドから除外する。
~~~~~~~~~~~
Mark Explanations Memo
* 全てが一致 "*.txt"の場合、拡張子「txt」のみを含める
? 任意の1文字が一致 "MyFile?.txt" の場合「MyFile1.txt」一致、「MyFile11.txt」は不一致
[sequence] 連続する任意の文字に一致
[!sequence] 連続しない文字に一致

2)--delete

* [同期元にない] AND [同期先にある] オブジェクトは削除

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html

より抜粋
~~~~~~~~
--delete (boolean)
Files that exist in the destination
 but not in the source are deleted during sync.
同期元(destination)に存在し、同期先(source)に存在しないファイルは、
同期中に削除されます。

Note that files excluded by filters are excluded from deletion.
フィルタで除外されたファイルは削除から除外されます。
~~~~~~~~

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-sync

より抜粋
~~~~~~~~
--delete オプションを使用する場合、
--exclude オプションと --include オプションによって、
s3 sync オペレーション中に削除するファイルやオブジェクトをフィルタリングできます。
この場合、パラメータ文字列で、ターゲットディレクトリまたはバケットに関連して、
削除から除外するか、削除に含めるファイルを指定する必要があります。
~~~~~~~~

ちなみに、この公式ドキュメントの例は、結構いい加減、、、
(それでハマった、、、)
=> 「3)--deleteオプション + --excludeオプションした際の指定の仕方」で確認した方がいい

例1

###############
# 事前準備
###############
# helloworld.txt, helloaws.txt, hello.txtを追記
$ echo HelloWorld > helloworld.txt
$ echo HelloAWS > helloaws.txt
$ echo Hello > hello.txt

###############
# 同期する 
###############

# 同期する
$ aws s3 sync ./ s3://your-s3-bucket

# 同期後、S3内の「hello.txt」を確認
$ aws s3 ls s3://your-s3-bucket
helloworld.txt
helloaws.txt
hello.txt

# hello.txtを削除する
$ rm ./hello.txt

$ ls
helloworld.txt
helloaws.txt

# 同期する
$ aws s3 sync ./ s3://your-s3-bucket --delete

# S3内のファイルを一覧表示する
$ aws s3 ls s3://your-s3-bucket
helloworld.txt
helloaws.txt

例2

# 同期元(Local)
+ src
   + main.py
   + lib/

# 同期先(s3)
s3://your-s3-bucket/
 + main.py
 + lib/
 + resources/
 + sqls/

# 同期
aws s3 sync \
 --delete \
 --include '*' --exclude 'resources/*' --exclude 'sqls/*' \
 ./src s3://your-s3-bucket/

3)--size-only / --exact-timestamps

[1] --size-only

* サイズが同じファイルは処理しない (デフォルト)

[2] --exact-timestamps

* S3からローカルに同期し、
 同じサイズのアイテムはタイムスタンプが正確に一致した場合は、何もしない
 => それ以外は、同期元⇒同期先でSyncする
* デフォルトの動作は、ローカルのバージョンが
 S3のバージョンよりも新しいものでない限り、
 同じサイズのアイテムを何もしない

4)--no-progress / --quiet / --only-show-errors

[1] --no-progress

* ファイル転送の進行状況は表示されない
* --quiet オプションと --only-show-errors オプションが指定されていない場合にのみ適用
* CI/CDとか使用する際は付けといたほうがいい

https://dev.classmethod.jp/articles/tsnote-s3-do-not-show-progress-in-the-log/
--quiet

* 一切出力されない

* --only-show-errors

* エラー / 警告のみ出力

【3】使用上の注意

1)--exact-timestamps を付けといた方がいい

* つけないと、[ファイル更新あり] AND [ファイルサイズは同じ] の場合、更新されない
 => デフォルトだと、ファイルサイズが同じなら何もしない
* ただし、ファイル名を変更する等対策が取れていればつけなくてもいい

2)--include / --excludeは、後に指定する方を優先する

* 後に指定するほうが優先する


https://docs.aws.amazon.com/cli/latest/reference/s3/#use-of-exclude-and-include-filters

# .txtで終わるファイルを除くすべてのファイルがコマンドから除外
--exclude "*" --include "*.txt"

# 後の「--exclude "*"」が優先なので
# すべてのファイルがコマンドから除外される
--include "*.txt" --exclude "*"

3)--deleteオプション + --excludeオプションした際の指定の仕方

* --excludeオプションは、更新元 or 更新先を基準に
 「<ファイル名>」もしくは「<ディレクトリ名>/*」などで指定する
 => 実装する前に、実際の環境などで --dryrun(ドライラン)オプションを
  付けて試した方がいい

構成例

#############
# 更新元
#############
MyPython.py
...

#############
# 更新先
#############
s3://your-s3-bucket/path
 + MyPython.py
 + ...
 + Input.env << ★除外したい
 + resources/ << ★除外したい
 + dbt/ << ★除外したい

コマンド例

aws s3 sync . s3://your-s3-bucket/path \
--delete --exclude "Input.env" --exclude "resources/*" --exclude "dbt/*"
# NG case ...  --exclude "/resources/*" などじゃ意図したように動作しない

参考文献

https://qiita.com/kurono/items/d16f74e9c83e0574d766
https://qiita.com/kanadeee/items/122acbf6bc069c36b4da
https://ebc-2in2crc.hatenablog.jp/entry/2021/02/11/181333

関連記事

Amazon S3 ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2017/03/06/212734
Amazon S3aws s3api ~
https://dk521123.hatenablog.com/entry/2024/05/22/235922
S3権限周りのトラブルシュート
https://dk521123.hatenablog.com/entry/2024/01/04/000000