pobierz ostatnio zmodyfikowany obiekt z S3 CLI

80

Mam przypadek użycia, w którym programowo wywołuję instancję EC2, kopiuję i plik wykonywalny z S3, uruchamiam go i zamykam instancję (zrobione w danych użytkownika). Muszę pobrać tylko ostatni dodany plik z S3. Czy istnieje sposób na pobranie ostatnio zmodyfikowanego pliku / obiektu z zasobnika S3 przy użyciu interfejsu wiersza polecenia?

życzliwy
źródło
czy w ogóle możesz zaangażować język programowania
Drew
CLI będzie najlepszą opcją, ponieważ planuję mieć go w danych użytkownika podczas uruchamiania instancji.
Wishy
Czy programujesz w jakichś językach z s3?
Drew
1
Czy istnieje lepsze rozwiązanie dla łyżek z przedmiotami 2 mln +?
lonewarrior556
1
Myślę, że w przypadku wielu obiektów lepszym rozwiązaniem byłoby utworzenie Event/Lambdaobiektu na obiekcie, który jest wyzwalany ObjectCreation. pobranie ostatniego obiektu spośród ponad 2 mln obiektów za pomocą s3 cli lub api jest o wiele wolniejsze.
Vaulstein,

Odpowiedzi:

174

Możesz wyświetlić listę wszystkich obiektów w zasobniku za pomocą 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

Są sortowane alfabetycznie według kluczy, ale ta pierwsza kolumna to czas ostatniej modyfikacji. Szybka zmiana sortkolejności ich według daty:

$ 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 1wybiera ostatni wiersz i awk '{print $4}'wyodrębnia czwartą kolumnę (nazwę obiektu).

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

Wreszcie, upuść to aws s3 cpdo pobrania obiektu:

$ KEY=`aws s3 ls $BUCKET --recursive | sort | tail -n 1 | awk '{print $4}'`
$ aws s3 cp s3://$BUCKET/$KEY ./latest-object
David Murray
źródło
2
Genialny post. Szczególnie przydatne ze względu na objaśnienia do każdego polecenia. Dzięki.
Christian
4
S3 indeksuje obiekty tylko według klucza. Jeśli w zasobniku jest wystarczająco dużo obiektów, że „skanowanie całej tabeli” w celu znalezienia tego, którego szukasz, jest niepraktyczne, musisz utworzyć własny, oddzielny indeks. Najbardziej leniwą opcją, jaką przychodzi mi do głowy, jest umieszczenie klucza ostatnio napisanego obiektu w s3: // $ BUCKET / current po jego napisaniu i poproszenie czytelników, aby tam zajrzeli, aby znaleźć, który z nich powinni pociągnąć.
David Murray
Na marginesie, jeśli chcesz zrobić to samo dla całego „folderu”, awkbędziesz musiał wybrać drugi element (zamiast czwartego) i --recursivebędzie potrzebny, np.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
To nie zadziała w przypadku zasobników zawierających więcej niż 1000 pozycji, ponieważ to najwięcej, co można zwrócić docs.aws.amazon.com/cli/latest/reference/s3/ls.html
nico
ta linia nie zadziała aws s3 cp s3://$BUCKET/$KEY ./latest-object, powróci poprzedni skrypt"object"
Madeo
23

Po chwili jest mała aktualizacja, jak to zrobić trochę elegancko:

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

Zamiast dodatkowej reversefunkcji możemy pobrać ostatni wpis z listy za pomocą[-1]

Stara odpowiedź:

To polecenie po prostu wykonuje zadanie bez żadnych zewnętrznych zależności:

aws s3api list-objects-v2 --bucket "my-awesome-bucket" --query 'reverse(sort_by(Contents, &LastModified))[:1].Key' --output=text
Roman Shishkin
źródło
3
Świetny. Jeśli potrzebujesz również nazwy obiektu, aby pasowała do określonego ciągu:--query 'reverse(sort_by(Contents[?contains(Key, `myKey`)], &LastModified))[:1].Key'
bfcapell
5
--query jest wykonywane lokalnie, więc jeśli masz w zasobniku więcej niż 1000 plików, nie masz gwarancji, że jako pierwsze otrzymasz ostatnio zmodyfikowane.
Gismo Ranas
@GismoRanas Słuszna uwaga. Zwykłą --filteropcję można zastosować, aby zmniejszyć listę
Roman Shishkin
11
aws s3api list-objects-v2 --bucket "bucket-name" |jq  -c ".[] | max_by(.LastModified)|.Key"
AlexLoo
źródło
Jeśli nigdy wcześniej nie spotkałeś jq, to ​​jest to procesor json stedolan.github.io/jq
andrew lorien
3
Myślę, że list-objects-v2ma limit maksymalnej liczby przedmiotów, więc jeśli twoje wiadro ma więcej obiektów niż to - to może nie dać dokładnej odpowiedzi
Gilad Peleg
docs.aws.amazon.com/cli/latest/reference/s3api/… stwierdza (w chwili pisania tego tekstu), że maksymalny limit na stronę wynosi 1000. Należy również zauważyć, że wynik ma IsTruncatedwartość true, jeśli dostępnych jest więcej kluczy do zwrócenia.
Ashutosh Jindal,
2

Poniżej znajduje się skrypt bash, który pobiera najnowszy plik z S3 Bucket. Użyłem AWS S3 SynchZamiast tego , aby nie pobierał pliku z S3, jeśli już istnieje.

--exclude, wyklucza wszystkie pliki

--include, zawiera wszystkie pliki pasujące do wzorca

#!/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 Dzięki @David Murray

AjitChahal
źródło
1

Jeśli jest to świeżo przesłany plik, możesz użyć Lambda do wykonania fragmentu kodu na nowym obiekcie S3.

Jeśli naprawdę potrzebujesz najnowszego, możesz nazwać swoje pliki datą najpierw, posortować według nazwy i wybrać pierwszy obiekt.

Jonathan Turpie
źródło
2
Niestety nie jest to świeżo przesłany plik. Będę potrzebował ostatniego przesłanego pliku, który mógł zostać przesłany w dowolnym momencie.
życzliwy