Рубрики
Без рубрики

Автоматическое удаление файлов из Bucket Amazon S3 с подпаски в течение продолжительности с помощью Python

Удаление файлов/объектов из ковша Amazon S3, которые находятся внутри подпапок внутри ведра/ведра. Tagged с Amazon, S3, Boto3, Python.

В соответствии с Amazon :

Amazon Web Services (AWS) – самая полная и широко принятая облачная платформа в мире, предлагающая более 165 полностью представленных сервисов из центров обработки данных во всем мире. Миллионы клиентов, включая самые быстрорастущие стартапы, крупнейшие предприятия и ведущие правительственные учреждения, являются AWS для владения своей инфраструктурой, становятся более гибкими и более низкими затратами.

Одним из многочисленных услуг Amazon является простой сервис хранения, широко известный как S3. Amazon S3 – отличный способ хранения файлов в течение короткого или долгосрочного. Многие учреждения во многом зависят от Amazon S3 (облачный, например, проверенный март 2019 г.) для хранения файлов, от файлов журнала в формате TXT, до бабушки-сестра дяди. Фотографии, которые мой будущий сын собрал. Вы понимаете, что я имею в виду.

Это служба хранения объектов, которая предлагает ведущую в отрасли масштабируемость, доступность данных, безопасность и производительность. Это означает, что институты всех форм и размеров могут использовать их для хранения своих данных для всех вариантов использования. Amazon утверждает, что предлагает конкурентоспособные цены, но это не то, о чем я буду писать. Через некоторое время человек захочет очистить некоторые, если не все файлы, хранящиеся на Amason S3 по ряду причин. Они могут включать соблюдение требований, когда учреждение взимается для сохранения определенных данных/файлов в течение определенного количества продолжительности, сохранение пространства-вы заряжаете Amazon за размер файлов, которые вы сохранили на S3, так что вам лучше удалить неиспользованные файлы, и только для этого.

Почему бы вам просто не перейти на консоль S3 и не удалить желаемый файл, или написать код оболочки, чтобы рекурсивно удалить эти файлы? Что ж, удачи, если у вас есть более 2 миллионов записей файлов, сохраненных в течение длительного периода времени. Может быть, друг тетя моего сына может помочь вам.

Я столкнулся с задачей удаления некоторых файлов из ведра Amazon S3 моей компании, и ниже я пошел на это. С помощью одного @Davidolinsky, который помог мне почистить его. Awscli не очень помог, так как мне нужно было контролировать то, что я удаляю и что я оставляю. Этот код был написан на Python. Мое предположение для Структура ведра является следующим образом с датами их файлов;

├── [ 160 Jun 10 15:05]  my_s3_bucket
│   ├── [ 128 Jun 10 15:05]  level-one-folder1
│   │   └── [ 608 Jun 10 15:18]  another-sub-folder
│   │       ├── [   0 Mar 26  2015]  file1.jpg
│   │       ├── [   0 Mar 26  2015]  file10.jpg
│   │       ├── [   0 Mar 26  2015]  file2.jpg
│   │       ├── [   0 Mar 26  2015]  file3.jpg
│   │       ├── [   0 Mar 26  2015]  file4.jpg
│   │       ├── [   0 Mar 26  2015]  file5.jpg
│   │       ├── [   0 Mar 26  2015]  file6.jpg
│   │       ├── [   0 Mar 26  2015]  file7.jpg
│   │       ├── [   0 Mar 26  2015]  file8.jpg
│   │       ├── [   0 Mar 26  2015]  file9.jpg
│   │       ├── [ 416 Jun 10 15:19]  folder-inside-sub-folder
│   │       │   ├── [   0 Mar 26  2010]  culp1.test
│   │       │   ├── [   0 Mar 26  2010]  culp10.test
│   │       │   ├── [   0 Mar 26  2010]  culp2.test
│   │       │   ├── [   0 Mar 26  2010]  culp3.test
│   │       │   ├── [   0 Mar 26  2010]  culp4.test
│   │       │   ├── [   0 Mar 26  2010]  culp5.test
│   │       │   ├── [   0 Mar 26  2010]  culp6.test
│   │       │   ├── [   0 Mar 26  2010]  culp7.test
│   │       │   ├── [   0 Mar 26  2010]  culp8.test
│   │       │   └── [   0 Mar 26  2010]  culp9.test
│   │       ├── [   0 Jun 10 15:17]  newer1.config
│   │       ├── [   0 Jun 10 15:17]  newer2.config
│   │       ├── [   0 Jun 10 15:17]  newer3.config
│   │       ├── [   0 Jun 10 15:17]  newer4.config
│   │       └── [   0 Jun 10 15:17]  newer5.config
│   └── [ 384 Jun 10 15:35]  level-one-folder2
│       ├── [   0 Mar 26  2005]  old1.txt
│       ├── [   0 Mar 26  2005]  old10.txt
│       ├── [   0 Mar 26  2005]  old2.txt
│       ├── [   0 Mar 26  2005]  old3.txt
│       ├── [   0 Mar 26  2005]  old4.txt
│       ├── [   0 Mar 26  2005]  old5.txt
│       ├── [   0 Mar 26  2005]  old6.txt
│       ├── [   0 Mar 26  2005]  old7.txt
│       ├── [   0 Mar 26  2005]  old8.txt
│       └── [   0 Mar 26  2005]  old9.txt
  1. Бото3
  2. время
  3. система

Вы можете установить Boto3, запустив PIP установить BOTO3 из вас используют пип или Conda установить Boto3 Или любым способом, что вы можете установить модули Python. Boto3 – это библиотека Python от Amazon, используемая для доступа к своим услугам. Вы можете посетить https://aws.amazon.com/ Для всей информации о их библиотеках и услугах.

import boto3
import time
import sys

Мы импортируем Boto3 Чтобы иметь возможность получить доступ к нашим услугам S3, время Чтобы помочь в качестве контрольной точки на время от Теперь (Что может быть любое установленное время) и Sys Чтобы сгенерировать вывод ошибок в терминал.

Давайте установим наши переменные. Обратите внимание на значения заполнителей.

# todays\'s epoch
_tday = time.time()
duration = 86400*180 #180 days in epoch seconds
#checkpoint for deletion
_expire_limit = tday-duration
# initialize s3 client
s3_client = boto3.client('s3')
my_bucket = "my-s3-bucket"
my_ftp_key = "my-s3-key/"
_file_size = [] #just to keep track of the total savings in storage size

Выше приведено прямо с комментариями, но в случае, если вам понадобится больше объяснений, вы можете продолжить читать этот абзац. Вы можете посмотреть PEP 8 Руководство по стилю именования для Python по причинам подчеркивания на случай, если вам любопытно. Я студент этой области, так любезно терпеть меня по своим ошибкам.

Мы можем установить конкретное текущее время для нашего приложения для проверки, но для большинства я просто буду использовать _tday как текущая дата.

Продолжительность это Unix Epoch Время, на которое будет установлен файл (любой файл, старше этой даты, будет удален). Здесь мы устанавливаем 180 дней (шесть месяцев) в эпохи UNIX.

_expire_limit будет просто разница между текущей датой и продолжительностью, которая нам нужна. Любая подшипчатая дата последней модифицированной даты меньше, чем значение старше и будет удалено.

S3_Client Будет просто называть низкий уровень Amazon S3 Client для его методов/функций.

my_bucket будет имя ведра, в котором содержатся файлы. Файлы могут находиться в подпапке (ы) в ведре. Не волнуйтесь, мы позаботимся об этом.

my_ftp_key будет имя определенной подпапки в ведре, из которого вы хотите найти файлы. Если у вас нет подпапков, вы можете игнорировать что -либо ключ что я упоминаю (прошел как префикс ).

Мы будем использовать _file_size держать размер в байты из всех файлов, которые были обработаны.

_del_size будет сбрасываться непрерывно, когда файлы удалятся и помогут нам определить общий размер, удаленный даже при возникновении ошибки.

Далее будут наши функции.

#works to only get us key/file information
def get_key_info(bucket="my-s3-bucket", prefix="my-s3-key/"):

    print(f"Getting S3 Key Name, Size and LastModified from the Bucket: {bucket} with Prefix: {prefix}")

    key_names = []
    file_timestamp = []
    file_size = []
    kwargs = {"Bucket": bucket, "Prefix": prefix}
    while True:
        response = s3_client.list_objects_v2(**kwargs)
        for obj in response["Contents"]:
            # exclude directories/folder from results. Remove this if folders are to be removed too
            if "." in obj["Key"]:
                key_names.append(obj["Key"])
                file_timestamp.append(obj["LastModified"].timestamp())
                file_size.append(obj["Size"])
        try:
            kwargs["ContinuationToken"] = response["NextContinuationToken"]
        except KeyError:
            break

    key_info = {
        "key_path": key_names,
        "timestamp": file_timestamp,
        "size": file_size
    }
    print(f'All Keys in {bucket} with {prefix} Prefix found!')

    return key_info


# Check if date passed is older than date limit
def _check_expiration(key_date=_tday, limit=_expire_limit):
    if key_date < limit:
        return True


# connect to s3 and delete the file
def delete_s3_file(file_path, bucket=my_bucket):
    print(f"Deleting {file_path}")
    s3_client.delete_object(Bucket=bucket, Key=file_path)
    return True


# check size deleted
def _total_size_dltd(size):
    _file_size.append(size)
    _del_size = round(sum(_file_size)/1.049e+6, 2) #convert from bytes to mebibytes
    return _del_size

get_key_info Функция принимает два параметра, а Ведро имя и Префикс , все, что будет передано методу клиента S3 под названием list_objects_v2 Анкет Этот метод принимает пару аргументов, одним из которых является Продолжение Анкет list_objects_v2 Метод способен вернуть только 1000 записей Pereach Call. Amazon использует Парень Метод, который возвращает нам ключ для нас, чтобы использовать следующий набор из 1000 записей на случай, если у вас будет гораздо больше файлов.

Ради ясности давайте представить себе книгу с около 10 страниц. Каждый раз, когда вы открываете страницу, вы можете увидеть только то, что находится на этой конкретной странице. Вы знаете, что есть больше страниц, потому что внизу Прямо есть текст, который читает 2/10 Анкет Учитывая, что строки на страницах продолжаются со страницы 1 по 10, и каждая страница имеет 10 строк, мы знаем, что страница 2 начнется с 11 до 20, а страница 5 начнется с 41 до 50.

Вот как list_objects_v2 работает. Каждый раз, когда мы делаем звонок, он возвращает нам начальный номер следующей страницы, чтобы мы могли сделать следующий вызов, сообщающий list_objects_v2 Чтобы начать получить нам следующий набор, начиная с этого номера.

Это достигается здесь в течение некоторого цикла, где после каждого вызова мы пытаемся сбросить Продолжение Пока мы не достигнем блокировщика, который будет Keyerror Анкет

Важно проверить синтаксис ответа, чтобы узнать, какую информацию вам потребуется от этого объекта. На нашей заботе информация о нашей файле живет в пределах "Содержание" ключ.

Мы только вернули key_info Объект, поскольку задание этой функции состоит в том, чтобы вернуть нам только соответствующую информацию, которая нам нужна из вызова.

_check_expiration принимает только два параметра. Если к нему ничего не передается, то он будет использовать значения по умолчанию из вышеупомянутых переменных. Он только возвращает Верно для каждого файла, когда Полномодированный Дата на S3 старше, чем продолжительность установки.

delete_s3_file принимает file_path который является пути файла на S3, начиная с ключа (префикс). Не сдается в ведро, он по умолчанию будет по умолчанию MY_Bucket.

_total_size_dltd отслеживает размеры хранилища удаленных файлов в MB. Простой Инструмент преобразования Google может помочь. В любой момент времени, если есть какие -либо ошибки, если файл был удален, мы будем представлены с удаленным общим размером.

Наконец, нам нужно запустить наше приложение. Это приложение можно назвать/ссылаться на любой другой проект, который у вас есть до тех пор, пока вы понимаете, о чем представляет собой каждая часть. Мы начнем с запуска нашего сохраненного файла Python напрямую, чтобы следующий код;

if __name__ == "__main__":
    try:
        s3_file = get_key_info()
        for i, fs in enumerate(s3_file["timestamp"]):
            file_expired = _check_expiration(fs)
            if file_expired: #if True is recieved
                file_deleted = delete_s3_file(s3_file["key_path"][i])
                if file_deleted: #if file is deleted
                    _del_size = _total_size_dltd(s3_file["size"][i])

        print(f"Total File(s) Size Deleted: {_del_size} MB")
    except:
        print ("failure:", sys.exc_info()[1])
        print(f"Total File(s) Size Deleted: {_del_size} MB")

В случае, если ваше ведро имя my_bucket и ваш префикс или ключ my_ftp_key Тогда запуск этого без прохождения какого -либо параметра пройдет через папку my_ftp_key Внутри my_bucket и удалить любой файл старше 180 дней с момента запуска приложения.

Теперь я продемонстрирую, как удалить старые файлы из вашей предполагаемой структуры папок.

  1. Если мы решим удалить более старые файлы внутри Папка-внутренняя-подключаемость Только это будет наш звонок.
if __name__ == "__main__":
    try:
        # the difference is right here
        s3_file = get_key_info("my_s3_bucket", "folder-inside-sub-folder")
        for i, fs in enumerate(s3_file["timestamp"]):
            # you can pass the duration in epoch as second parameter
            file_expired = _check_expiration(fs)
            if file_expired:
                file_deleted = delete_s3_file(s3_file["key_path"][i])
                if file_deleted:
                    _del_size = _total_size_dltd(s3_file["size"][i])

        print(f"Total File(s) Size Deleted: {_del_size} MB")
    except:
        print ("failure:", sys.exc_info()[1])
        print(f"Total File(s) Size Deleted: {_del_size} MB")
  1. Если мы хотим удалить все старые файлы из level-one-cholder1 Наш звонок будет
if __name__ == "__main__":
    try:
        # the difference is right here
        s3_file = get_key_info("my_s3_bucket", "level-one-folder1")
        for i, fs in enumerate(s3_file["timestamp"]):
            # you can pass the duration in epoch as second parameter
            file_expired = _check_expiration(fs)
            if file_expired:
                file_deleted = delete_s3_file(s3_file["key_path"][i])
                if file_deleted:
                    _del_size = _total_size_dltd(s3_file["size"][i])

        print(f"Total File(s) Size Deleted: {_del_size} MB")
    except:
        print ("failure:", sys.exc_info()[1])
        print(f"Total File(s) Size Deleted: {_del_size} MB")

Это удалит все более старые файлы внутри Другой-восхищенный а также Папка-внутренняя-подключаемость Поскольку они внутри level-one-cholder1 Анкет Однако, если мы проверяем на 180 дней более старых файлов, то файлы новее1.config к новее5.config Внутри другого взрыва не будет затронута, так как они не проходят истекший тест.

Я уверен, что вы можете подумать о многих других способах использования этого кода для вызова удалений на своем ведре S3 в зависимости от продолжительности, будь то из сценария процесса с использованием ARGV или настройки ежемесячного автоматического процесса для выполнения технического обслуживания. Ниже приведено резюме

import boto3
import time
import sys

# todays\'s epoch
_tday = time.time()
duration = 86400*180 #180 days in epoch seconds
#checkpoint for deletion
_expire_limit = tday-duration
# initialize s3 client
s3_client = boto3.client('s3')
my_bucket = "my-s3-bucket"
my_ftp_key = "my-s3-key/"
_file_size = [] #just to keep track of the total savings in storage size

#Functions
#works to only get us key/file information
def get_key_info(bucket="my-s3-bucket", prefix="my-s3-key/"):

    print(f"Getting S3 Key Name, Size and LastModified from the Bucket: {bucket} with Prefix: {prefix}")

    key_names = []
    file_timestamp = []
    file_size = []
    kwargs = {"Bucket": bucket, "Prefix": prefix}
    while True:
        response = s3_client.list_objects_v2(**kwargs)
        for obj in response["Contents"]:
            # exclude directories/folder from results. Remove this if folders are to be removed too
            if "." in obj["Key"]:
                key_names.append(obj["Key"])
                file_timestamp.append(obj["LastModified"].timestamp())
                file_size.append(obj["Size"])
        try:
            kwargs["ContinuationToken"] = response["NextContinuationToken"]
        except KeyError:
            break

    key_info = {
        "key_path": key_names,
        "timestamp": file_timestamp,
        "size": file_size
    }
    print(f'All Keys in {bucket} with {prefix} Prefix found!')

    return key_info


# Check if date passed is older than date limit
def _check_expiration(key_date=_tday, limit=_expire_limit):
    if key_date < limit:
        return True


# connect to s3 and delete the file
def delete_s3_file(file_path, bucket=my_bucket):
    print(f"Deleting {file_path}")
    s3_client.delete_object(Bucket=bucket, Key=file_path)
    return True


# check size deleted
def _total_size_dltd(size):
    _file_size.append(size)
    _del_size = round(sum(_file_size)/1.049e+6, 2) #convert from bytes to mebibytes
    return _del_size


if __name__ == "__main__":
    try:
        s3_file = get_key_info()
        for i, fs in enumerate(s3_file["timestamp"]):
            file_expired = _check_expiration(fs)
            if file_expired: #if True is recieved
                file_deleted = delete_s3_file(s3_file["key_path"][i])
                if file_deleted: #if file is deleted
                    _del_size = _total_size_dltd(s3_file["size"][i])

        print(f"Total File(s) Size Deleted: {_del_size} MB")
    except:
        print ("failure:", sys.exc_info()[1])
        print(f"Total File(s) Size Deleted: {_del_size} MB")

Я надеюсь, что я смог помочь вам решить проблему, которую вы можете столкнуться. Этот урок неполный, если вы не критикуете его, поскольку это делает усердную работу, чтобы быть лучше в том, что я делаю. Оставьте комментарии, если вам нужно. Вы можете копировать/повторить вышеприведенное для вашего использования, но знаете, что используете его на свой собственный риск. Я не несет ответственности за какие -либо ущерб, которые могут возникнуть из -за вашего использования для вас или третьей стороны.

Оригинал: “https://dev.to/gm456742/automatically-delete-files-from-amazon-s3-bucket-with-subfolders-over-a-duration-using-python-53go”