Скрипт Shell-/Bash для удаления старых резервных файлов по имени и определенному шаблону

Вопрос или проблема

каждый из наших файлов резервной копии базы данных создается. Файлы именуются следующим образом:

prod20210528_1200.sql.gz 
шаблон: prod`date +\%Y%m%d_%H%M`

Шаблон можно настроить при необходимости.

Я хотел бы, чтобы у меня был скрипт, который:

  • хранит все резервные копии за последние x (например, 3) дня
  • для резервных копий старше x (например, 3) дня следует сохранять только резервную копию с временем 00:00
  • для резервных копий старше y (например, 14) дней следует сохранять только один файл в неделю (понедельник)
  • для резервных копий старше z дней (например, 90) следует сохранять только один файл в месяц (1-е число каждого месяца)
  • скрипт должен использовать имя файла вместо информации о дате (создании) файла, если это возможно
  • скрипт должен запускаться каждый день

К сожалению, у меня очень мало знаний о языке сценариев shell/bash.
Я бы сделал что-то вроде этого:

if (file < today - x AND date > today - (x + 1))
{
  if (%H_of_file != 00 AND %M_of_file != 00)
  {  
    delete file
  }
}

if (file < today - y AND date > today - (y + 1))
{
  if (file != Monday)
  {  
    delete file
  }
}

if (file < today - z AND date > today - (z + 1))
{
  if (%m_of_file != 01)
  {  
    delete file
  }
}

Это имеет для вас какой-либо смысл?

Большое спасибо! 

Всего наилучшего,
Фантом

Это работает для меня (BSD date, не GNU date)

#!/usr/local/bin/bash
DIR_BACKUPS='/backups'
KEEP_DAILY=3
KEEP_WEEKLY=14
KEEP_MONTHLY=90

date_keep_daily=$(date -j -v-${KEEP_DAILY}d +"%Y%m%d")
date_keep_weekly=$(date -j -v-${KEEP_WEEKLY}d +"%Y%m%d")
date_keep_monthly=$(date -j -v-${KEEP_MONTHLY}d +"%Y%m%d")

for file in $DIR_BACKUPS/prod*.sql.gz; do
    timestamp=${file#*onwalt}
    timestamp=${timestamp%%.*}
    date_of_file=${timestamp%%_*}
    hour_of_file=${timestamp:(-4):2}

    if [[ $date_of_file < $date_keep_monthly ]]; then
        if [[ $(date -jf "%Y%m%d_%H%M" $timestamp +"%d") != 01 ]]; then
            rm $file
        fi
    elif [[ $date_of_file < $date_keep_weekly ]]; then
        if [[ $(date -jf "%Y%m%d_%H%M" $timestamp +"%u") != 1 ]]; then
            rm $file
        fi
    elif [[ $date_of_file < $date_keep_daily ]]; then
        if [[ $(date -jf "%Y%m%d_%H%M" $timestamp +"%H") != 00 ]]; then
            rm $file
        fi
    fi
done

Как коммиттер pyExpireBackups, я могу указать вам реализацию ExpirationRule моего решения (исходный код ниже и в репозитории github). Он использует mtime

 modified = datetime.datetime.fromtimestamp(stats.st_mtime, tz=datetime.timezone.utc)

для оценки “возраста” файла.

См. https://wiki.bitplan.com/index.php/PyExpireBackups для документации.

Скрипт установки:

pip install PyExpireBackups

установит команду shell “expireBackups”.
Использование:

expireBackups -h
использование: expireBackups [-h] [-d] [--days DAYS] [--weeks WEEKS] [--months MONTHS] [--years YEARS]
                     [--minFileSize MINFILESIZE] [--rootPath ROOTPATH] [--baseName BASENAME] [--ext EXT]
                     [--createTestFiles CREATETESTFILES] [-f] [-V]

Истечение сроков резервного копирования на основе правил (ежегодно, ежемесячно, еженедельно, ежедневно ...)

  Создано Вольфгангом Фалем 2022-04-01.
  Авторское право 2008-2022 Вольфганг Фаль. Все права защищены.

  Лицензировано по лицензии Apache 2.0
  http://www.apache.org/licenses/LICENSE-2.0

  Распространяется на условиях "КАК ЕСТЬ" без каких-либо гарантий
  или условий любого рода, как явных, так и подразумеваемых.

ИСПОЛЬЗОВАНИЕ

дополнительные аргументы:
  -h, --help            показать это сообщение и выйти
  -d, --debug           показать информацию для отладки
  --days DAYS           количество последовательных дней, для которых нужно сохранить ежедневную резервную копию (по умолчанию: 7)
  --weeks WEEKS         количество последовательных недель, для которых нужно сохранить еженедельную резервную копию (по умолчанию: 6)
  --months MONTHS       количество последовательных месяцев, для которых нужно сохранить ежемесячную резервную копию (по умолчанию: 8)
  --years YEARS         количество последовательных лет, для которых нужно сохранить ежегодную резервную копию (по умолчанию: 4)
  --minFileSize MINFILESIZE
                        минимальный размер файла в байтах для фильтрации (по умолчанию: 1)
  --rootPath ROOTPATH
  --baseName BASENAME   основное имя для фильтрации (по умолчанию: None)
  --ext EXT             расширение для фильтрации (по умолчанию: None)
  --createTestFiles CREATETESTFILES
                        создать заданное количество временных тестовых файлов (по умолчанию: None)
  -f, --force
  -V, --version         показать номер версии программы и выйти

Пример выполнения приведет к:

expireBackups --ext .tgz
хранят 7 файлов для ежедневного резервного копирования
хранят 6 файлов для еженедельного резервного копирования
хранят 8 файлов для ежемесячного резервного копирования
хранят 4 файла для ежегодного резервного копирования
истечение 269 файлов, сухой запуск
#   1✅:   0.0 days(    5 GB/    5 GB)→./sql_backup.2022-04-02.tgz
#   2✅:   3.0 days(    5 GB/    9 GB)→./sql_backup.2022-03-30.tgz
#   3✅:   4.0 days(    5 GB/   14 GB)→./sql_backup.2022-03-29.tgz
#   4✅:   5.0 days(    5 GB/   18 GB)→./sql_backup.2022-03-28.tgz
#   5✅:   7.0 days(    5 GB/   23 GB)→./sql_backup.2022-03-26.tgz
#   6✅:   9.0 days(    5 GB/   27 GB)→./sql_backup.2022-03-24.tgz
#   7✅:  11.0 days(    5 GB/   32 GB)→./sql_backup.2022-03-22.tgz
#   8❌:  15.0 days(    5 GB/   37 GB)→./sql_backup.2022-03-18.tgz
#   9❌:  17.0 days(    5 GB/   41 GB)→./sql_backup.2022-03-16.tgz
#  10✅:  18.0 days(    5 GB/   46 GB)→./sql_backup.2022-03-15.tgz
#  11❌:  19.0 days(    5 GB/   50 GB)→./sql_backup.2022-03-14.tgz
#  12❌:  20.0 days(    5 GB/   55 GB)→./sql_backup.2022-03-13.tgz
#  13❌:  22.0 days(    5 GB/   59 GB)→./sql_backup.2022-03-11.tgz
#  14❌:  23.0 days(    5 GB/   64 GB)→./sql_backup.2022-03-10.tgz
#  15✅:  35.0 days(    4 GB/   68 GB)→./sql_backup.2022-02-26.tgz
#  16❌:  37.0 days(    4 GB/   73 GB)→./sql_backup.2022-02-24.tgz
#  17❌:  39.0 days(    4 GB/   77 GB)→./sql_backup.2022-02-22.tgz
#  18❌:  40.0 days(    5 GB/   82 GB)→./sql_backup.2022-02-21.tgz
#  19✅:  43.0 days(    4 GB/   86 GB)→./sql_backup.2022-02-18.tgz
...
...
# 264✅:1426.0 days(    4 GB/    1 TB)→./sql_backup.2018-05-07.tgz
# 265❌:1433.0 days(    4 GB/    1 TB)→./sql_backup.2018-04-30.tgz
# 266❌:1447.0 days(    4 GB/    1 TB)→./sql_backup.2018-04-16.tgz
# 267❌:1482.0 days(    4 GB/    1 TB)→./sql_backup.2018-03-12.tgz
# 268❌:1489.0 days(    4 GB/    1 TB)→./sql_backup.2018-03-05.tgz
# 269❌:1509.0 days(    4 GB/    1 TB)→./sql_backup.2018-02-12.tgz
сохранили 24 файла   105 ГБ

.

Ответ или решение

Скрипт для удаления старых резервных копий с использованием Bash

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

Описание задачи

Файлы ваших резервных копий именуются по следующему шаблону: prodYYYYMMDD_HHMM.sql.gz. Вам требуется, чтобы скрипт выполнял следующие действия:

  1. Сохранять все резервные копии за последние 3 дня.
  2. Хранить только одну резервную копию в день (в 00:00) для файлов старше 3 дней.
  3. Хранить одну резервную копию в неделю (по понедельникам) для файлов старше 14 дней.
  4. Хранить одну резервную копию в месяц (1 числа каждого месяца) для файлов старше 90 дней.

Bash-скрипт

#!/bin/bash

# Определяем переменные
DIR_BACKUPS='/backups'         # Путь к директории с резервными копиями
KEEP_DAILY=3                   # Количество дней для ежедневных резервных копий
KEEP_WEEKLY=14                 # Количество дней для еженедельных резервных копий
KEEP_MONTHLY=90                # Количество дней для ежемесячных резервных копий

# Получаем даты для определения удаляемых файлов
date_keep_daily=$(date -d "-${KEEP_DAILY} days" +"%Y%m%d")
date_keep_weekly=$(date -d "-${KEEP_WEEKLY} days" +"%Y%m%d")
date_keep_monthly=$(date -d "-${KEEP_MONTHLY} days" +"%Y%m%d")

# Проходим по всем файлам резервных копий
for file in $DIR_BACKUPS/prod*.sql.gz; do
    # Извлекаем дату и время из имени файла
    timestamp=$(basename "$file" .sql.gz)  
    date_of_file=${timestamp:4:8}           # YYYYMMDD
    hour_of_file=${timestamp:13:2}          # HH

    if [[ $date_of_file < $date_keep_monthly ]]; then
        # Удаляем, если это не 1-е число месяца
        if [[ $(date -d "$date_of_file" +"%d") != "01" ]]; then
            rm "$file"
        fi
    elif [[ $date_of_file < $date_keep_weekly ]]; then
        # Удаляем, если это не понедельник
        if [[ $(date -d "$date_of_file" +"%u") != "1" ]]; then
            rm "$file"
        fi
    elif [[ $date_of_file < $date_keep_daily ]]; then
        # Удаляем, если это не 00:00
        if [[ $hour_of_file != "00" ]]; then
            rm "$file"
        fi
    fi
done

Автоматизация выполнения скрипта

Для автоматического выполнения скрипта каждый день вы можете использовать планировщик задач cron. Для этого выполните команду:

crontab -e

Добавьте следующую строку, чтобы запускать скрипт каждый день в 2:00 ночи:

0 2 * * * /bin/bash /path/to/your_script.sh

Заключение

Этот Bash-скрипт позволяет эффективно управлять резервными копиями базы данных, обеспечивая сохранность важной информации и удаляя лишние данные согласно установленным правилам. Регулярное использование скрипта не только освободит место на диске, но и поможет поддерживать порядок в резервных копиях. Если у вас есть дополнительные требования или изменения в шаблоне именования файлов, вы можете легко адаптировать скрипт под свои нужды.

Оцените материал
Добавить комментарий

Капча загружается...