отримати останній змінений об'єкт з S3 CLI


80

У мене є випадок використання, коли я програмно викликаю екземпляр EC2, копіюю та виконуваний файл із S3, запускаю його та вимикаю екземпляр (це робиться в даних користувача). Мені потрібно отримати лише останній доданий файл із S3. Чи є спосіб отримати останній змінений файл / об'єкт із сегмента S3 за допомогою CLI?


Ви можете взагалі залучити мову програмування
Дрю

CLI буде найкращим варіантом, оскільки я планую мати його в даних користувача під час запуску екземпляра.
Бажання

Ви програмуєте будь-якими мовами за допомогою s3?
Дрю

1
Чи є краще рішення для сегментів із об'єктами 2М +?
lonewarrior556

1
Для багатьох об’єктів, я думаю, кращим рішенням було б створити Event/Lambdaна об’єкті, який запускається ObjectCreation. отримання останнього об'єкта з 2M + об'єктів за допомогою s3 cli або api - це спосіб повільніше.
Вольштейн

Відповіді:


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 після того, як ви його написали, і нехай читачі шукають там, щоб знайти, який із них слід витягнути.
Девід Мюррей

Тільки допоміжна примітка, якщо ви хочете зробити те саме для цілої "папки", 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
Девід Аренбург,

3
Це не буде працювати на відра з більш ніж 1000 пунктів, тому що це найбільше , що може бути повернутий docs.aws.amazon.com/cli/latest/reference/s3/ls.html
Nico

цей рядок не буде працювати aws s3 cp s3://$BUCKET/$KEY ./latest-object. Попередній сценарій повернеться"object"
Мадео

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зменшення списку можна застосувати звичайний варіант
Роман Шишкін

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що існує обмеження на максимальну кількість предметів, тому, якщо у вашому відрі більше об’єктів, ніж це - це може не отримати точної відповіді
Гілад Пелег

docs.aws.amazon.com/cli/latest/reference/s3api/… стверджує (на момент написання статті), що максимальне обмеження на сторінку становить 1000. Також зауважте, що результат IsTruncatedвстановив значення true, якщо для повернення доступно більше клавіш.
Ashutosh Jindal

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
На жаль, це не щойно завантажений файл. Мені знадобиться останній завантажений файл, який міг бути завантажений у будь-який час.
бажання
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.