【发布时间】:2016-07-05 18:26:10
【问题描述】:
S3 存储桶是否有关于上次更新时间的信息?如何找到桶中的任何个对象上次更新的时间?
【问题讨论】:
标签: python amazon-web-services amazon-s3 boto aws-cli
S3 存储桶是否有关于上次更新时间的信息?如何找到桶中的任何个对象上次更新的时间?
【问题讨论】:
标签: python amazon-web-services amazon-s3 boto aws-cli
桶 last modified time没有原生支持。我这样做的方法是使用 aws cli ,对输出进行排序,取底线并打印前 2 个字段。
$ aws s3 ls mybucket --recursive | sort | tail -n 1 | cut -d ' ' -f1,2
2016-03-18 22:46:48
【讨论】:
在撰写本文时,基于简单的性能测试,一个简单的高性能命令的最佳折衷方案是 aws s3 ls --recursive(选项 #2)
s3cmd
(参见s3cmd Usage,或使用sudo pip install s3cmd 浏览installing 之后的手册页)
s3cmd ls s3://the-bucket | sort| tail -n 1
s3
aws s3 ls the-bucket --recursive --output text | sort | tail -n 1 | awk '{print $1"T"$2","$3","$4}'
(请注意,上面的 awk 指的是 GNU awk。如果您需要安装它以及 macOS 上的任何其他 GNU 实用程序,请参阅 this)
s3api
(使用list-objects 或list-objects-v2)
aws s3api list-objects-v2 --bucket the-bucket | jq -r '.[] | max_by(.LastModified) | [.Key, .LastModified, .Size]|@csv'
请注意,这两个s3api 命令都是分页的,处理分页是列表对象的v2 中的fundamental improvement。
如果存储桶有超过 1000 个对象(使用 s3cmd du "s3://ons-dap-s-logs" | awk '{print $2}' 获取对象数量),那么您需要处理 API 的分页并进行多次调用以获取自 @987654327 以来的所有结果返回结果中的@ 是UTF-8 binary order 而不是'Last Modified'。
这里是对同一个桶执行的上述三种方法的简单性能比较。为简单起见,存储桶中的对象少于 1000 个。这是查看执行时间的单线:
export bucket_name="the-bucket" && \
( \
time ( s3cmd ls --recursive "s3://${bucket_name}" | awk '{print $1"T"$2","$3","$4}' | sort | tail -n 1 ) & ; \
time ( aws s3 ls --recursive "${bucket_name}" --output text | awk '{print $1"T"$2","$3","$4}' | sort | tail -n 1 ) & ; \
time ( aws s3api list-objects-v2 --bucket "${bucket_name}" | jq -r '.[] | max_by(.LastModified) | [.LastModified, .Size, .Key]|@csv' ) & ; \
time ( aws s3api list-objects --bucket "${bucket_name}" | jq -r '.[] | max_by(.LastModified) | [.LastModified, .Size, .Key]|@csv' ) &
) >! output.log
(output.log 将存储每个命令列出的最后修改的对象)
上面的输出如下:
( s3cmd ls --recursive ...) 1.10s user 0.10s system 79% cpu 1.512 total
( aws s3 ls --recursive ...) 0.72s user 0.12s system 74% cpu 1.128 total
( aws s3api list-objects-v2 ...) 0.54s user 0.11s system 74% cpu 0.867 total
( aws s3api list-objects ...) 0.57s user 0.11s system 75% cpu 0.900 total
对于相同数量的返回对象,aws s3api 调用的性能明显更高;但是,处理 API 的分页会带来额外的(脚本)复杂性。
有用的链接:
看Leveraging s3 and s3api了解aws s3和aws s3api的区别
【讨论】:
正如其他人所评论的那样,没有什么神奇的元数据可以存储这些信息。您只需遍历对象即可。
使用boto3 执行此操作的代码:
import boto3
from datetime import datetime
def bucket_last_modified(bucket_name: str) -> datetime:
"""
Given an S3 bucket, returns the last time that any of its objects was
modified, as a timezone-aware datetime.
"""
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)
objects = list(bucket.objects.all())
return max(obj.last_modified for obj in objects)
【讨论】:
我的解决方法是使用“last_updated”键和unix时间戳将bucket_metadata.json文件写入存储桶:
{ "last_updated": 1634243586 }
然后,每当您更新存储桶时,您都会生成另一个时间戳并重新写入文件。
【讨论】:
关于 GET BUCKET 对象版本的 Amazon S3 API 规范(位于:http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETVersion.html)表示返回了 LastModified 属性 - 但我不确定它是否会随着每个对象的更改而更新...
【讨论】:
LastModified: "object 上次修改的日期和时间。"为每个单独的对象版本 返回此属性。它不是存储桶本身的单个值。