отримати останній змінений об'єкт з 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.