sync . --delete from the wrong directory
`aws s3 sync . s3://bucket/ --delete` 是最危险的 S3 错误:在错误目录里跑,就会把那里的文件同步过去,同时把桶里其他所有文件删光。
⚠ 常见坑: 防范:来源永远写到有名字的构建目录(./dist ./build ./out),每次首次部署前跑 --dryrun,用桶策略限制只有 CI IAM 主体才能写入。
例子aws s3 sync ./dist s3://my-site/ --delete --dryrun
aws s3 sync ./dist s3://my-site/ --delete
single PUT is limited to 5 GB
单次 put-object 超过 5GB 的文件会报 EntityTooLarge。高层 aws s3 cp 默认超过 8MB 自动切换分段上传;s3api put-object 不会自动切换。
⚠ 常见坑: 单分段上限 5GB。对象总大小上限 5TB(需要分段上传)。每个分段 ≥ 5MB(最后一段除外)。未完成的分段上传持续计费,务必设置生命周期规则自动终止。
例子aws s3 cp ./huge-backup.tar.gz s3://my-bucket/ --multipart-chunksize 100MB
list paginates silently at 1000 keys
`aws s3 ls` 最多返回 1000 条,没有翻页提示。list-objects-v2 同样默认 1000 条。如果响应有 NextContinuationToken,说明还有更多对象。
例子aws s3 ls s3://my-bucket/ --recursive | wc -l
aws s3api list-objects-v2 --bucket my-bucket --query "length(Contents)"
--acl is ignored when Object Ownership is enforced
2023 年 4 月起新建桶默认 "Bucket owner enforced" Object Ownership,ACL 被禁用。上传时传 --acl public-read 会报 AccessControlListNotSupported。公开访问改用桶策略。
例子aws s3api get-bucket-ownership-controls --bucket my-bucket
aws s3api put-bucket-ownership-controls --bucket my-bucket --ownership-controls Rules=[{ObjectOwnership=BucketOwnerPreferred}] cross-account access requires two grants
跨账号读取需要两个授权同时满足:(1) 源桶策略给目标账号/角色授予 s3:GetObject;(2) 目标账号 IAM 策略给该账号/角色授予访问该桶 ARN 的 s3:GetObject。缺一不可,否则 AccessDenied。
⚠ 常见坑: KMS 加密对象还需要第三层:KMS 密钥策略也必须允许目标账号使用密钥解密。三层都要检查:桶策略、身份策略、KMS 密钥策略。
例子aws s3api get-bucket-policy --bucket src-bucket
aws s3api get-bucket-encryption --bucket src-bucket
cross-region data transfer is billed
跨 region 复制 S3 对象有数据传输费用(约 $0.02/GB)。同 region 内 S3-S3 传输免费。同 region 的 EC2→S3 免费;跨 region 有费用。
例子aws s3 cp s3://us-bucket/data s3://eu-bucket/data --recursive --source-region us-east-1 --region eu-west-1
get-bucket-location returns null for us-east-1
get-bucket-location 对 us-east-1 的桶返回空 LocationConstraint,不是字符串 "us-east-1"。自动化脚本里务必把 null 标准化为 "us-east-1"。
例子aws s3api get-bucket-location --bucket my-bucket
REGION=$(aws s3api get-bucket-location --bucket my-bucket --query "LocationConstraint" --output text); REGION=${REGION:-us-east-1} bucket names are globally unique and lowercase
S3 桶名在整个 AWS 所有账号中全局唯一,不仅仅是你的账号。必须小写,3-63 字符,不含下划线和大写字母。任何账号占用了这个名字就报 BucketAlreadyExists。
例子aws s3 mb s3://mycompany-prod-data-2024
versioning cannot be fully disabled once enabled
桶一旦开启版本控制,只能暂停(suspend),无法彻底关闭。暂停状态下已有历史版本仍然保留;新上传的对象使用 null 版本 ID。所有历史版本继续计费直到被显式删除。
例子aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Suspended
aws s3api list-object-versions --bucket my-bucket --query "Versions[].{Key:Key,VersionId:VersionId}" incomplete multipart uploads accumulate charges
每个发起了但从未 complete 或 abort 的分段上传,都会在桶里留下游离的分段,以标准存储类型计费。这些分段不出现在 aws s3 ls 的结果里。用 list-multipart-uploads 查找。
⚠ 常见坑: 最佳实践:给任何使用分段上传 API 的桶都加一条 7 天后 AbortIncompleteMultipartUpload 的生命周期规则。这是防止无声存储成本积累的零成本保障。
例子aws s3api list-multipart-uploads --bucket my-bucket
aws s3api abort-multipart-upload --bucket my-bucket --key file.gz --upload-id <UploadId>