Сохранение n самых последних каталогов в резервной копии script

У меня есть каталог в /home/backup/, который хранит ежегодные резервные копии. Внутри папки резервного копирования у нас есть следующие каталоги:

/home/backup/2012
/home/backup/2013
/home/backup/2014
/home/backup/2015
/home/backup/2016
/home/backup/2017

и каждый год мне приходится очищать данные, сохраняя только последние три года резервного копирования.

В приведенном выше случае я должен удалить:

/home/backup/2012
/home/backup/2013
/home/backup/2014

Каков наилучший способ найти каталоги, которые нужно удалить? У меня есть это, но он не работает:

find /home/ecentrix/recording/ -maxdepth 1 -mindepth 1 -type d -ctime +1095 -exec rm -rf {} \;

Есть ли у вас другая идея сделать это?

Ответ 1

Так как ваши каталоги имеют четко определенные и целые имена, я просто использую bash для вычисления соответствующих целей:

mkdir -p backup/201{2..7} # just for testing

cd backup
rm -fr $(seq 2012 $(( $(date +"%Y") - 3)))

seq генерирует список чисел с 2012 по текущий год минус 3, которые затем передаются в rm, чтобы взорвать их.

Ответ 2

Решение

# Check if extended globbing is on
shopt extglob

# If extended globbing is off, run this line
shopt -s extglob

# Remove all files except 2015, 2016, and 2017
rm -r -i /home/backup/!(2015|2016|2017)

# Turn off extended globbing (optional)
shop -u extglob

Объяснение

shopt -s extglob позволяет вам сопоставлять любые файлы, кроме внутри !(...). Таким образом, строка означает удаление любого файла в /home/backup кроме 2015, 2016 или 2017.

Флаг -i в rm -r -i ... позволяет вам интерактивно подтвердить удаление каждого файла. Удалите -i, если вы хотите, чтобы файлы были удалены автоматически.

Динамические даты

Это решение действует для автоматизации (например, заданий cron)

# Number of latest years to keep
LATEST_YEARS=3

# Get the current year
current_year=$(date '+%Y')

# Get the first/earliest year to keep
first_year=$(( current_year - $(($LATEST_YEARS - 1)) ))

# Turn on extended globbing
shopt -s extglob

# Store years to keep in an array
keep_years=( $(seq $first_year $current_year) )

# Specify files to keep
rm -r /home/backup/!(${keep_years[0]}|${keep_years[1]}|${keep_years[2]})

ПРИМЕЧАНИЕ: ВСЕ ФАЙЛЫ В СПИСКЕ РЕЗЕРВОВ БУДУТ УДАЛЕНЫ, ЗА ИСКЛЮЧЕНИЕМ ПОСЛЕДНИХ 3 ЛЕТ

Ответ 3

Более общее решение

Я думаю, что лучше всего перемещаться по каталогам в порядке убывания, а затем удалять их после третьего. Таким образом, нет никакой опасности потерять каталог, когда script запускается снова и снова:

#!/bin/bash
backups_to_keep=3
count=0
cd /home/backup
while read -d '' -r dir; do
  [[ -d "$dir" ]]                || continue  # skip if not directory
  ((++count <= backups_to_keep)) && continue  # skip if we are within retaining territory
  echo "Removing old backup directory '$dir'" # it is good to log what was cleaned up
  echo rm -rf -- "$dir"
done < <(find . -maxdepth 1 -name '[2-9][0-9][0-9][0-9]' -type d -print0 | sort -nrz)

Удалите echo до rm -rf после тестирования. Для вашего примера он дает этот вывод:

rm -rf -- ./2014
rm -rf -- ./2013
rm -rf -- ./2012
  • cd /home/backup ограничивает rm -rf только этим каталогом для дополнительной безопасности
  • find . -maxdepth 1 -name '[2-9][0-9][0-9][0-9]' -type d предоставляет каталоги верхнего уровня, соответствующие glob
  • sort -nrz гарантирует, что новые каталоги будут первыми, -z обрабатывает вывод с нулевым завершением find ... -print0
  • Это решение не требует жесткого кодирования в течение многих лет - он просто предполагает, что удаляемые каталоги названы в численном порядке
  • Он устойчив к любым другим файлам или каталогам, находящимся в каталоге резервного копирования.
  • Никаких побочных эффектов, если script запускается снова и снова
  • Это можно легко расширить, чтобы поддерживать различные соглашения об именах для каталога резервного копирования - просто измените выражение glob

Ответ 4

Рассмотрим это:

find /home/backup/2* -maxdepth 1 | sort -r | awk "NR>3" | xargs rm -rf

Как это работает

  • Создайте список имен файлов, начинающихся с "2", только под /home/backup/

  • В алфавитном порядке отсортируйте список в обратном порядке.

  • Используйте AWK для фильтрации количества строк в списке. NR задает количество строк, отсортированных по обратным сортировкам. Вы можете изменить это число 3, чтобы быть тем самым много строк, которые вы хотите оставить. Поэтому, если вам нужны только последние два года, измените значение 3 на 2. Если вы хотите сохранить последние 10, сделайте это "NR > 10".

  • Добавить результирующий список в команду "rm -rf".

Запуск как выделенный пользователь, для безопасности

Опасность здесь в том, что я предлагаю rm -rf. Это рискованно. Если что-то пойдет не так, вы можете удалить вещи, которые хотите сохранить. Я уменьшаю этот риск, только вызывая эти команды выделенным пользователем, который ТОЛЬКО имеет разрешения на удаление файлов резервных копий (и не за его пределами).

Merit

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

Демонстрация

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

find test01/2* -maxdepth 1 | sort -r | awk "NR>4" | xargs echo rm -rf

Я использовал NR > 4, а не NR > 3 (как вам бы хотелось), потому что NR > 4 показывает, что мы выбираем, сколько строк удалить из списка и, следовательно, не удалять.

Вот что я получаю: Демонстрация

Вторичная команда выше изменила заключительный этап, чтобы не повторять, что он будет делать, но на самом деле это сделать.

У меня есть грубая копия дампа этого в script, поскольку я использую его на некоторых моих серверах, вы можете просмотреть его здесь: https://github.com/docdawning/teenybackup

Требуется для успеха

Этот подход ЗАВИСИТ ОТ алфавитизации любой команды find. В моем случае я использую даты типа ISO-8601, которые полностью предназначены для сортировки по дате, когда они в алфавитном порядке. Ваши даты типа YYYY полностью соответствуют требованиям.

Дополнительная безопасность

Я рекомендую вам изменить свои резервные копии для хранения в архивах tar. Затем вы можете изменить rm -rf на простое rm. Это намного безопаснее, хотя и не безупречно. Независимо от того, вы действительно должны запускать это как выделенный непривилегированный пользователь (как вы должны сделать для любого script, вызывающего удаление, на мой взгляд).

Имейте в виду, что если вы запустите его с помощью

find /home/backup

Тогда вызов xargs будет включать /home/backup, что было бы катастрофой, потому что он тоже будет удален. Поэтому вы должны искать в этом пути. Вместо того, чтобы называть его с помощью приведенного ниже:

find /home/backup/* 

2 *, приведенное выше, является лишь способом ограничения операции поиска.

Гарантия

Отсутствует; это Интернет. Быть осторожен. Испытайте вещи, чтобы убедить себя. Кроме того, возможно, некоторые автономные резервные копии тоже.


Наконец - ранее я опубликовал это как ответ, но совершил роковую ошибку, представляя команду find, основанную на /home/backup, а не /home/backup/ * или/home/backup/2 *. Это вызвало /home/backup, которое также было отправлено для удаления, что было бы катастрофой. Это очень маленькое различие, о котором я уже говорил выше. Я удалил этот предыдущий ответ и заменил его на этот.

Ответ 5

Вот один из способов.

Обновленный ответ.

[dev]$ find backup/*  | grep -vE "$(date '+%Y')|$(date +%Y --date='1 year ago')|$(date +%Y --date='2 year ago')" | xargs  rm -rfv

removed directory: ‘backup/2012’
removed directory: ‘backup/2013’
removed directory: ‘backup/2014’

Ответ 6

если вы хотите удалить каталог, введите следующую команду

sudo rm -r [folder name]
#in your case it will be 
sudo rm -r /home/backup/2012
sudo rm -r /home/backup/2013
sudo rm -r /home/backup/2014