Сохранение n последних каталогов в сценарии резервного копирования

у меня есть каталог, в /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 {} ;

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

6 ответов


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

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

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

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


решение

# 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 ЛЕТ


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

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

#!/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
  • это решение не жестко кодирует годы - оно просто предполагает, что удаляемые каталоги называются численно сортируемым способом
  • он устойчив к любым другим файлам или каталогам, присутствующим в каталоге резервного копирования
  • есть никаких побочных эффектов, если скрипт запускается снова и снова
  • это может быть легко расширено для поддержки различных соглашений об именах для каталога резервного копирования-просто измените выражение glob

рассмотрим следующий пример:

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

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

  1. Создайте список имен файлов, начиная с "2", только в разделе /дома/резервное копирование/

  2. сортировка списка в алфавитном порядке, в обратном порядке.

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

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

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

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

достоинства

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

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

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

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

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

вот что я получаю: Demonstration

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

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

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

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

Дополнительную Безопасность

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

имейте в виду, что если вы начнете его с

find /home/backup

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

find /home/backup/* 

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

гарантии

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


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


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

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

[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’

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

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