こんにちは、Reoです。
フリーランスのインフラエンジニアとして働きながら、インフラ学習サービス「InfraDojo(インフラ道場)」を運営しています。
S3を使い始めると、こんな疑問が出てきます。
「画面ではフォルダになっているのに、なぜプレフィックスと呼ぶの?」
「logs/ と logs では、何が違うの?」
今回は、S3のオブジェクトキーとプレフィックスを整理し、AWS CLIで一覧を確認する方法を紹介します。
S3では、パス全体がオブジェクトの名前になる
この記事では、S3の汎用バケットを扱います。
最初に、次の3つの用語を押さえましょう。
| 用語 | 意味 |
|---|---|
| バケット | オブジェクトを保存する入れ物 |
| オブジェクト | 保存するデータと、それに付随する情報 |
| オブジェクトキー | バケット内でオブジェクトを識別する名前 |
たとえば、次のようなキーがあるとします。
logs/app/access.log
Linuxのパスに似ていますが、S3では logs/app/access.log 全体が一つのキーです。
汎用バケットは、ファイルシステムのようなディレクトリ階層を持ちません。コンソールでは、共通するキーの先頭部分を使って、フォルダのように表示しています。AWSの説明
図の例では、次の2つが logs/ から始まっています。
logs/app/access.log
logs/app/error.log
この共通する先頭の文字列が、プレフィックスです。
プレフィックスは「先頭の文字列」で絞り込む
プレフィックスは、フォルダ名だけを指すものではありません。
次のキーに対して、
logs/app/access.log
logs/ も、logs/app/ も、先頭から一致する文字列です。
S3の一覧取得では、指定したプレフィックスから始まるキーを絞り込めます。プレフィックスによる整理と一覧取得
ここで気を付けたいのが、末尾の / です。
たとえば、バケット内に次のキーがあるとします。
logs/app/access.log
logs/app/error.log
logs-archive/old.log
指定するプレフィックスによって、対象が変わります。
| 指定する文字列 | 一致する対象 |
|---|---|
logs |
上の3つすべて |
logs/ |
最初の2つ |
logs/app/ |
最初の2つ |
logs-archive/old.log も、先頭の4文字は logs です。
そのため、「logsフォルダの中を見たい」という意図なら、logs/ まで指定すると範囲を合わせやすくなります。
AWS CLIでキーを一覧表示する
ここからは、次の3つのオブジェクトがある想定で確認します。
logs/app/access.log
logs/app/error.log
images/logo.png
実行には、次の準備が必要です。
- AWS CLI v2が使えること
- 対象アカウントへの認証が済んでいること
- 対象バケットに対する
s3:ListBucketが許可されていること
以下はBashやZshなどで実行する例です。your-bucket-name を自分のバケット名に置き換えてください。
aws s3api list-objects-v2 \
--bucket your-bucket-name \
--prefix "logs/" \
--query 'Contents[].Key' \
--output json \
--no-cli-pager
各指定の意味は次のとおりです。
| 指定 | 役割 |
|---|---|
--bucket |
対象バケットを指定 |
--prefix |
キーの先頭が一致するものに絞る |
--query 'Contents[].Key' |
応答からキーだけを取り出す |
--output json |
JSON形式で表示 |
list-objects-v2 は一覧取得の操作です。今回の実行に、オブジェクト本体を読むための s3:GetObject は必要ありません。AWS CLIの仕様
想定する出力は次のとおりです。
[
"logs/app/access.log",
"logs/app/error.log"
]
images/logo.png は logs/ から始まらないため、含まれません。
出力は説明用の例です。実際の結果は、バケット内のキーと権限によって変わります。
フォルダのように一段ずつ見るには?
先ほどのコマンドでは、logs/ から始まるキーを、その下の階層に見える部分まで含めて取得しました。
一方で、画面のフォルダ表示のように、ひとまとまりで見たい場合もあります。
そのときに使うのが、区切り文字を指定する --delimiter です。
aws s3api list-objects-v2 \
--bucket your-bucket-name \
--prefix "logs/" \
--delimiter "/" \
--query 'CommonPrefixes[].Prefix' \
--output json \
--no-cli-pager
同じ想定データなら、次の結果になります。
[
"logs/app/"
]
logs/ の後ろから次の / までが共通するキーを、logs/app/ としてまとめています。
ここで表示された logs/app/ は、共通するプレフィックスをまとめた一覧結果です。ディレクトリの実体を取得したわけではありません。
使い分けは、次のように整理できます。
| 見たいもの | 指定 |
|---|---|
| 指定した文字列から始まるキー | --prefix |
| さらに区切り文字でまとめた結果 |
--prefix と --delimiter
|
なお、今回の2つ目のコマンドは CommonPrefixes だけを表示しています。logs/readme.txt のような直下のオブジェクトは Contents 側に入り、この表示には出ません。一覧取得時のグループ化
「フォルダを作成」すると何ができる?
S3コンソールには、フォルダを作成する操作もあります。
汎用バケットで logs というフォルダを作ると、コンソールは logs/ というキーの0バイトのオブジェクトを作成します。コンソールでのフォルダ作成
そのため、実際のバケットでは、一覧に次のようなキーが含まれることもあります。
logs/
logs/app/access.log
logs/app/error.log
ただし、logs/app/access.log を保存するために、事前に logs/ というオブジェクトを作る必要はありません。
フォルダのように見える表示と、実際に存在するキーを分けて考えると、CLIの結果を理解しやすくなります。
キーを確認する習慣を付けよう
S3で目的のデータが見つからないときは、まず次の点を確認してみてください。
- バケット名は合っているか
- キーの先頭部分は合っているか
- プレフィックス末尾の
/を含めているか -
ContentsとCommonPrefixesのどちらを見ているか
画面上のフォルダ名だけでなく、実際のキーを見られるようになると、CLIやスクリプトでも対象を指定しやすくなります。
AWSの学習と並行して、ターミナル操作やコマンドの出力を読む練習を進めたい方は、InfraDojoも活用してみてください。
ブラウザ上のターミナルで、Linuxの基本操作を実際に入力しながら学べます。
▼ InfraDojo(インフラ道場)
