Abrufen des zuletzt geänderten Objekts von der S3-CLI

80

Ich habe einen Anwendungsfall, in dem ich programmgesteuert eine EC2-Instanz aufrufe, eine Datei aus S3 kopiere und ausführbar mache, sie ausführe und die Instanz herunterfahre (in Benutzerdaten). Ich muss nur die zuletzt hinzugefügte Datei von S3 erhalten. Gibt es eine Möglichkeit, die zuletzt geänderte Datei / das zuletzt geänderte Objekt mithilfe der CLI aus einem S3-Bucket abzurufen?

Wunsch
quelle
Können Sie überhaupt eine Programmiersprache einbeziehen
Drew
CLI ist die beste Option, da ich vorhabe, sie während des Starts der Instanz in den Benutzerdaten zu haben.
Wunsch
Programmieren Sie mit s3 in einer beliebigen Sprache?
Drew
1
Gibt es eine bessere Lösung für Eimer mit mehr als 2 Millionen Objekten?
lonewarrior556
1
Für viele Objekte wäre es meiner Meinung nach eine bessere Lösung, ein Event/LambdaObjekt zu erstellen , das ausgelöst wird ObjectCreation. Das Abrufen des letzten Objekts unter 2M + Objekten mit s3 cli oder api ist viel zu langsam.
Vaulstein

Antworten:

170

Sie können alle Objekte im Bucket auflisten mit 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

Sie sind alphabetisch nach Schlüsseln sortiert, aber diese erste Spalte ist die letzte geänderte Zeit. Ein kurzer sortwird sie nach Datum neu ordnen:

$ 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 1wählt die letzte Zeile aus und awk '{print $4}'extrahiert die vierte Spalte (den Namen des Objekts).

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

Zu guter Letzt legen Sie dies ab, aws s3 cpum das Objekt herunterzuladen:

$ KEY=`aws s3 ls $BUCKET --recursive | sort | tail -n 1 | awk '{print $4}'`
$ aws s3 cp s3://$BUCKET/$KEY ./latest-object
David Murray
quelle
2
Genialer Beitrag. Besonders nützlich aufgrund der Erläuterungen zu jedem Befehl. Vielen Dank.
Christian
4
S3 indiziert Objekte nur nach Schlüssel. Wenn der Bucket über genügend Objekte verfügt, dass ein "vollständiger Tabellenscan" zum Auffinden des gesuchten Objekts unpraktisch ist, müssen Sie einen eigenen Index erstellen. Die faulste Option, die ich mir vorstellen kann, besteht darin, den Schlüssel des zuletzt geschriebenen Objekts in s3: // $ BUCKET / current zu setzen, nachdem Sie es geschrieben haben, und die Leser dort nachsehen zu lassen, welches sie ziehen sollen.
David Murray
Nur eine Randnotiz, wenn Sie dasselbe für einen ganzen "Ordner" möchten, awkmuss das zweite Element (anstelle des vierten) auswählen und --recursivewird benötigt, z. B.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
Dies funktioniert nicht bei Eimern mit mehr als 1000 Artikeln, da höchstens docs.aws.amazon.com/cli/latest/reference/s3/ls.html
nico
Diese Zeile funktioniert nicht. aws s3 cp s3://$BUCKET/$KEY ./latest-objectDas vorherige Skript wird zurückgegeben"object"
Madeo
22

Nach einer Weile gibt es ein kleines Update, wie man es ein bisschen elegant macht:

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

Anstelle einer zusätzlichen reverseFunktion können wir den letzten Eintrag aus der Liste über erhalten[-1]

Alte Antwort:

Dieser Befehl erledigt den Job einfach ohne externe Abhängigkeiten:

aws s3api list-objects-v2 --bucket "my-awesome-bucket" --query 'reverse(sort_by(Contents, &LastModified))[:1].Key' --output=text
Roman Shishkin
quelle
3
Ausgezeichnet. Wenn Sie auch den Objektnamen benötigen, um mit einer bestimmten Zeichenfolge --query 'reverse(sort_by(Contents[?contains(Key, `myKey`)], &LastModified))[:1].Key'
übereinzustimmen
4
--query wird lokal ausgeführt. Wenn Sie also mehr als 1000 Dateien im Bucket haben, wird nicht garantiert, dass Sie die zuletzt geänderten zuerst erhalten.
Gismo Ranas
@ GismoRanas Guter Punkt. Die reguläre --filterOption kann angewendet werden, um eine Liste zu reduzieren
Roman Shishkin
11
aws s3api list-objects-v2 --bucket "bucket-name" |jq  -c ".[] | max_by(.LastModified)|.Key"
AlexLoo
quelle
Wenn Sie jq noch nie zuvor getroffen haben, ist es ein json-Prozessor stedolan.github.io/jq
andrew lorien
3
Ich denke, es list-objects-v2gibt eine Begrenzung für die maximale Anzahl von Gegenständen. Wenn Ihr Eimer also mehr Objekte enthält - dies wird möglicherweise keine genaue Antwort erhalten
Gilad Peleg
docs.aws.amazon.com/cli/latest/reference/s3api/… gibt (zum Zeitpunkt dieses Schreibens) an, dass das maximale Limit pro Seite 1000 beträgt. Beachten Sie auch, dass die Ausgabe IsTruncatedauf true gesetzt wurde, wenn mehr Schlüssel für die Rückgabe verfügbar sind.
Ashutosh Jindal
2

Es folgt ein Bash-Skript, das die neueste Datei von einem S3-Bucket herunterlädt. Ich habe stattdessen den Befehl AWS S3 Synch verwendet, damit die Datei nicht von S3 heruntergeladen wird, wenn sie bereits vorhanden ist.

--exclude, schließt alle Dateien aus

--include, enthält alle Dateien, die dem Muster entsprechen

#!/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 Danke @ David Murray

AjitChahal
quelle
1

Wenn es sich um eine frisch hochgeladene Datei handelt, können Sie mit Lambda einen Code für das neue S3-Objekt ausführen.

Wenn Sie wirklich die neueste benötigen, können Sie Ihre Dateien mit dem Datum zuerst benennen, nach Namen sortieren und das erste Objekt übernehmen.

Jonathan Turpie
quelle
2
Dies ist leider keine frisch hochgeladene Datei. Ich benötige die zuletzt hochgeladene Datei, die jederzeit hochgeladen werden konnte.
Wunsch