用 aws CLI 操作桶与对象
目标
用 aws CLI 熟悉 S3 兼容存储的基本操作——profile、存储桶、对象上传、前缀、列表、ETag、复制、元数据——并切身体会对象存储中没有目录这一事实。
为什么重要
理解 S3 API,并不是在学习某个特定厂商的产品。AWS S3、SeaweedFS、Garage、Ceph RGW、MinIO 说的全是同一套 API,所以这套 API 实际上就是一个可移植层。2025–2026 年 MinIO 社区版停止发布时,应用侧的迁移成本并不高,原因正在于此——只要更换端点和凭据,代码基本可以原样保留。本实验环境也经历了同样的事:服务器从 MinIO 换成了 SeaweedFS 的 S3 网关,但在这里输入的命令,放到 AWS 上一个字符都不用改就能运行。本实验特别要记住的是第 6 步的 ETag。单分段上传的 ETag 就是内容的 md5,因此客户端可以自行验证上传是否完整。在下一项实验中讲到分段上传的 ETag 与此有何不同时,这里学到的规则就是出发点。
步骤
- 用
aws configure set向 profilelocal写入四个值——aws_access_key_id、aws_secret_access_key、region、endpoint_url(http://127.0.0.1:9000)。凭据在/opt/fixtures/s3/creds.env中。aws --profile local s3 ls必须无错误地结束。 - 创建存储桶
lab-media。它必须出现在aws --profile local s3 ls的列表中。 - 把
/opt/fixtures/s3/logo.png上传为s3://lab-media/img/logo.png。 - 把
/opt/fixtures/s3/中的banner.png上传为img/banner.png,readme.txt上传为doc/readme.txt,sales.csv上传为doc/sales.csv。 - 把
aws --profile local s3 ls --recursive s3://lab-media的结果保存到/root/s3/list.txt。必须恰好是 4 行。 - 在
/root/s3/etag.txt中写入etag=<값>和md5=<값>(占位符均为具体的值)两行。logo.png的 ETag(去掉引号)必须与本地文件的 md5 相同。 - 把
doc/readme.txt以服务端复制的方式复制为doc/README.txt,然后删除原对象。aws --profile local s3 ls s3://lab-media/doc/中必须只有README.txt,而没有readme.txt。 - 用
text/csvContent-Type 重新上传sales.csv。aws --profile local s3api head-object --bucket lab-media --key doc/sales.csv的输出中,ContentType必须是text/csv。
参考
- 查看 profile:
aws configure list --profile local(密钥只显示最后四个字符) - 不想每次都加
--profile local时,可以用export AWS_PROFILE=local - 递归列表:
aws s3 ls --recursive s3://lab-media - 对象元数据:
aws s3api head-object --bucket lab-media --key img/logo.png - 指定 Content-Type:
aws s3 cp 파일 s3://버킷/키 --content-type text/csv(占位符依次为本地文件、存储桶、键) aws s3是像复制文件一样使用的高层命令,aws s3api则与每一次 S3 API 调用一一对应。想看实际传输了什么时,使用s3api。- 常见错误 1:在存储桶名称中使用大写字母或下划线——存储桶名称遵循 DNS 规则。
- 常见错误 2:把
img/误当成文件夹而想单独创建——它只是键名的一部分。
设置 S3 profile
用 aws configure set 向 profile local 写入 aws_access_key_id、aws_secret_access_key、region、endpoint_url(http://127.0.0.1:9000)四个值。凭据在 /opt/fixtures/s3/creds.env 中。aws --profile local s3 ls 必须无错误地结束。
把端点和凭据绑定到同一个 profile 中。凭据在 /opt/fixtures/s3/creds.env 里;如果漏掉 endpoint_url,CLI 就会尝试连接真正的 AWS。
创建存储桶
创建存储桶 lab-media。它必须出现在 aws --profile local s3 ls 的列表中。
存储桶名称遵循 DNS 规则——只能使用小写字母、数字和连字符。
上传一个对象
把 /opt/fixtures/s3/logo.png 上传为 s3://lab-media/img/logo.png。
同时指定本地路径和目标键。目标键中的斜杠不是文件夹,而是名称的一部分。
用前缀来整理
把 /opt/fixtures/s3/ 中的 banner.png 上传为 img/banner.png,readme.txt 上传为 doc/readme.txt,sales.csv 上传为 doc/sales.csv。
分别上传到 img/ 和 doc/ 之下。实际上并不会创建文件夹,只是键名变成了那个样子。
导出递归列表
把 aws --profile local s3 ls --recursive s3://lab-media 的结果保存到 /root/s3/list.txt。必须恰好是 4 行。
默认列表会按前缀折叠显示。有一个选项可以全部展开。
比较 ETag 与本地哈希
在 /root/s3/etag.txt 中写入 etag=<값> 和 md5=<값>(占位符均为具体的值)两行。logo.png 的 ETag(去掉引号)必须与本地文件的 md5 相同。
单分段上传的 ETag 就是内容的 md5。把两个值并排写出来进行比较。
服务端复制后删除原对象
把 doc/readme.txt 以服务端复制的方式复制为 doc/README.txt,然后删除原对象。aws --profile local s3 ls s3://lab-media/doc/ 中必须只有 README.txt,而没有 readme.txt。
没有重命名操作。先复制再删除,就是重命名。要让它在服务器上处理,不要经过下载。
指定 Content-Type 上传并确认
用 text/csv Content-Type 重新上传 sales.csv。aws --profile local s3api head-object --bucket lab-media --key doc/sales.csv 的输出中,ContentType 必须是 text/csv。
虽然也会根据扩展名推测,但明确指定更稳妥。查询对象元数据来确认。