S3CLIから最後に変更されたオブジェクトを取得します


80

プログラムでEC2インスタンスを起動し、S3から実行可能ファイルをコピーして実行し、それを実行してインスタンスをシャットダウンするというユースケースがあります(ユーザーデータで実行)。S3から最後に追加されたファイルのみを取得する必要があります。CLIを使用してS3バケットから最後に変更されたファイル/オブジェクトを取得する方法はありますか?


プログラミング言語を使用できますか
2015年

CLIは、インスタンスの起動時にユーザーデータに含める予定なので、最適なオプションになります。
希望の2015年

s3を使用して任意の言語でプログラムしますか?
2015年

1
2M以上のオブジェクトを含むバケットのより良いソリューションはありますか?
lonewarrior556 2017年

1
多くのオブジェクトの場合、より良い解決策は、Event/Lambdaでトリガーされるオブジェクトにを作成することだと思いますObjectCreation。s3 cliまたはapiを使用して2M以上のオブジェクトの中で最後のオブジェクトをフェッチすると、速度が低下します。
Vaulstein 2018

回答:


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}'、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--recursiveKEY=`aws s3 ls $BUCKET --recursive | sort | tail -n 1 | awk '{print $2}'` ; aws s3 cp s3://$BUCKET/$KEY ./latest-object --recursive
ちなみに

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を超えるファイルがある場合、最後に変更されたファイルを最初に取得することは保証されません。
GismoRanas20年

@GismoRanas良い点。通常の--filterオプションを適用してリストを減らすことができます
RomanShishkin20年

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

これまでjqに会ったことがない場合は、jsonプロセッサstedolan.github.io/jq
andrew lorien 2018

3
list-objects-v2最大アイテム数には制限があると思うので、バケットにそれよりも多くのオブジェクトがある場合、正確な答えが得られない可能性があります
Gilad Peleg 2018年

docs.aws.amazon.com/cli/latest/reference/s3api/… は、(この記事の執筆時点で)ページあたりの最大制限は1000であると述べています。またIsTruncated、返すキーがさらにある場合は、出力がtrueに設定されていることに注意してください。
AshutoshJindal19年

2

以下は、S3バケットから最新のファイルをダウンロードするbashスクリプトです。代わりにAWSS3 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ありがとう@DavidMurray


1

これが新しくアップロードされたファイルである場合は、Lambdaを使用して新しいS3オブジェクトでコードを実行できます。

本当に最新のものを取得する必要がある場合は、最初に日付を使用してファイルに名前を付け、名前で並べ替えて、最初のオブジェクトを取得できます。


2
残念ながら、これは新しくアップロードされたファイルではありません。いつでもアップロードできた可能性のある最後にアップロードされたファイルが必要になります。
希望の2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.