从S3 CLI获取最后修改的对象


80

我有一个用例,其中我以编程方式启动一个EC2实例,从S3复制和可执行文件,运行它并关闭该实例(在用户数据中完成)。我只需要从S3获取最后添加的文件。有没有办法使用CLI从S3存储桶中获取最后修改的文件/对象?


您是否可以完全使用一种编程语言
Drew

CLI是最好的选择,因为我计划在实例启动期间将其包含在用户数据中。
希望

您使用s3以任何语言编程吗?
2015年

1
对于具有2M +对象的存储桶,是否有更好的解决方案?
lonewarrior556

1
对于许多对象,我认为一个更好的解决方案是在上创建Event/Lambda触发了的对象ObjectCreation。使用s3 cli或api提取2M +个对象中的最后一个对象的方法较慢。
Vaulstein,

Answers:


174

您可以使用以下命令列出存储桶中的所有对象aws s3 ls $BUCKET --recursive

$ aws s3 ls $BUCKET --recursive
2015-05-05 15:36:17          4 an_object.txt
2015-06-08 14:14:44   16322599 some/other/object
2015-04-29 12:09:29      32768 yet-another-object.sh

它们是按字母顺序排序的,但是第一列是最后修改的时间。快速操作sort将按日期重新排序:

$ aws s3 ls $BUCKET --recursive | sort
2015-04-29 12:09:29      32768 yet-another-object.sh
2015-05-05 15:36:17          4 an_object.txt
2015-06-08 14:14:44   16322599 some/other/object

tail -n 1选择最后一行,并awk '{print $4}'提取第四列(对象的名称)。

$ aws s3 ls $BUCKET --recursive | sort | tail -n 1 | awk '{print $4}'
some/other/object

最后但并非最不重要的一点是,将其放入aws s3 cp下载对象中:

$ KEY=`aws s3 ls $BUCKET --recursive | sort | tail -n 1 | awk '{print $4}'`
$ aws s3 cp s3://$BUCKET/$KEY ./latest-object

2
辉煌的职位。由于每个命令的说明,它特别有用。谢谢。
基督徒

4
S3仅按键索引对象。如果存储桶中有足够的对象,以至于无法进行“全表扫描”来查找所需的对象,则需要构建自己的索引。我能想到的最懒惰的选择是在写完之后,将最近写入的对象的密钥放在s3:// $ BUCKET / current中,并让读者看那里去寻找应该拉的对象。
David Murray

只是附带说明一下,如果您想对整个“文件夹”使用相同的内容,awk则需要选择第二个元素(而不是第4个元素),并且--recursive需要,例如,KEY=`aws s3 ls $BUCKET --recursive | sort | tail -n 1 | awk '{print $2}'` ; aws s3 cp s3://$BUCKET/$KEY ./latest-object --recursive
David Arenburg

3
这不适用于包含1000个以上项目的存储桶,因为这是可以返回的最多的文档docs.aws.amazon.com/cli/latest/reference/s3/ls.html
nico

此行将不起作用aws s3 cp s3://$BUCKET/$KEY ./latest-object,先前的脚本将返回"object"
Madeo

23

一段时间后,有一个小小的更新,如何做起来有点优雅:

aws s3api list-objects-v2 --bucket "my-awesome-bucket" --query 'sort_by(Contents, &LastModified)[-1].Key' --output=text

除了额外的reverse功能,我们还可以通过以下方法从列表中获取最后一个条目:[-1]

旧答案:

此命令仅执行此工作而没有任何外部依赖项:

aws s3api list-objects-v2 --bucket "my-awesome-bucket" --query 'reverse(sort_by(Contents, &LastModified))[:1].Key' --output=text

3
优秀的。如果您还需要对象名称来匹配某个字符串:--query 'reverse(sort_by(Contents[?contains(Key, `myKey`)], &LastModified))[:1].Key'
bfcapell

5
--query是在本地执行的,因此如果存储桶中有1000个以上的文件,则不能保证先获取最后修改的文件。
Gismo Ranas

@GismoRanas好点。可以使用常规--filter选项来减少列表
Roman Shishkin

11
aws s3api list-objects-v2 --bucket "bucket-name" |jq  -c ".[] | max_by(.LastModified)|.Key"

如果您以前从未见过jq,那就是json处理器stedolan.github.io/jq
andrew lorien

3
我认为list-objects-v2最大物品数有限制,因此,如果您的存储桶中的物品数量超过限制,则可能无法获得准确的答案
Gilad Peleg,

docs.aws.amazon.com/cli/latest/reference/s3api/… 指出(截至撰写本文时)每页的最大限制为1000。另外请注意,IsTruncated如果有更多键可返回,则输出已设置为true。
阿舒托什·金达尔

2

以下是bash脚本,该脚本从S3存储桶下载最新文件。我改用AWS S3 Synch命令,因此如果已经存在,它将不会从S3下载文件。

--exclude,排除所有文件

--include,包括所有与模式匹配的文件

#!/usr/bin/env bash

    BUCKET="s3://my-s3-bucket-eu-west-1/list/"
    FILE_NAME=`aws s3 ls $BUCKET  | sort | tail -n 1 | awk '{print $4}'`
    TARGET_FILE_PATH=target/datdump/
    TARGET_FILE=${TARGET_FILE_PATH}localData.json.gz

    echo $FILE_NAME
    echo $TARGET_FILE

    aws s3 sync $BUCKET $TARGET_FILE_PATH --exclude "*" --include "*$FILE_NAME*"

    cp target/datdump/$FILE_NAME $TARGET_FILE

ps感谢@David Murray


1

如果这是一个新上传的文件,则可以使用Lambda在新的S3对象上执行一段代码。

如果您确实需要获取最新的文件,则可以使用日期优先,然后按名称排序并使用第一个对象来命名文件。


2
不幸的是,这不是一个新上传的文件。我需要可以随时上传的最后一个上传文件。
希望
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.