Давно стояла задача создания небольшого скрипта, по созданию резервных копий и восстановлению различных конфигурационных файлов.
Обрисую задачи, которые решает этот скрипт:
- Скрипт создаёт резервную копию конфига, дописывая к нему дату и время, и перемещает его в папку для хранения;
- Скрипт имеет ротацию, т.е. следит за кол-вом конфигов в папке и удаляет самый старый, если их число превышает заданное.
- Восстановление происходит через меню в 3 этапа:
- выбираем конфиг, который хотим восстановить.
- выбираем резервную копию для восстановления.
- подтверждаем наш выбор.
- Перед восстановлением скрипт делает резервную копию восстанавливаемого файла с пометкой "_before_restore".
- В скрипте присутвует быстрое восстановление всех конфигов на их последние резервные копии.
Сам код:
#!/bin/bash # # Config backup/restore # # AUTHOR: nol1ght (nol1ght.mail@gmail.com) # VERSION: 1.0 # LICENSE: public # #Устанавливаем разделитель Separator=";" #Устанавливаем путь до конфига backup_config="bconf_config" #Устанавливаем максимальное кол-во резервных копий конфигов configRotate=12; #Выбираем вид отображения диалогов. (dialog/xdialog/gdialog и все подобные) DIALOG=${DIALOG=dialog} #Переменная для копирования конфига перед восстановлением backupRestore="" number=-1; #Функция чтения конфига function read_config { #читаем построчно while read line do #увеличиваем счётчик ((number++)) #Записываем путь до конфига(в строке до разделителя) pathToConfig[${number}]=${line%%$Separator*}; #Записываем путь до каталога резервных копий(в строке после разделителя) pathToBackup[${number}]=${line#*$Separator}; done < $backup_config } #Установка переменных пути function paths { #Смотрим, есть ли параметры у функции if [ -z "$1" ] then #если нет - выходим exit fi #Записываем в переменную имя конфига + избавляемся от проблем с пробелами в имени файла configName=`basename ${pathToConfig[$1]} | sed 's/ /\?/g'` #Записываем в переменную путь до конфига + избавляемся от проблем с пробелами в имени файла pathToConf=`dirname ${pathToConfig[$1]} | sed 's/ /\?/g'` #Добавляем / в конец pathToConf=$pathToConf"/" #Записываем в переменную путь до резервных копий + избавляемся от проблем с пробелами в имени файла pathToBack=`echo ${pathToBackup[$1]} | sed 's/ /\?/g'` } #Функция резервного копирования function backup { #Смотрим есть ли параметры у функции if [ -z "$1" ] then #если нет - устанавливаем на перебор всех конфигов i_begin=0; max=$number; else #если да - устанавливаем на конкретный конфиг i_begin=$1; max=$1; fi #Перебираем конфиг(и) for ((i = $i_begin; i <= $max; i++)); do #Задаём переменные пути paths $i #Задаём имя резервной копии (формат - "имя конфига_ГГГГММДД_ЧЧММСС") backupName=$configName"_"$(date +%Y%m%d)"_"$(date +%H%M%S) #Создаём каталог для резернвых копий mkdir -p $pathToBack #Подсчитываем кол-во резервных копий в каталоге count=`cd $pathToBack;ls $pathToBack$configName_* | wc -l` #Создаём резервную копию cp $pathToConf$configName $pathToBack$backupName$backupRestore #Смотрим если число конфигов достигло максимального числа - удаляем последний. if [ $count -gt $configRotate ]; then ls -t -1 $pathToBack$configName_* | tail --lines 1 | xargs rm fi done } #Функция восстановления function restore { #Создаём временный файл temp_file=`tempfile 2> /dev/null` #Перебираем все конфиги for ((i = 0; i <= number; i++)); do #Подготавливаем строчку для меню dialog_config="$dialog_config $i \"${pathToConfig[$i]}\" " done #Отоброжаем меню $DIALOG --menu "Select config to restore" 30 60 30 $dialog_config 2> $temp_file #Читаем ответ conf=`cat $temp_file` #Если ничего не выбранно - выходим из программы. if [ -z $conf ];then clear exit fi #Задаём переменные пути paths $conf #Смотрим кол-во резервных копий в каталоге files=(`ls -t -1 $pathToBack$pathToConf_*`) max_index=$((${#files[@]} - 1)) #Перебираем все конфиги for ((i = 0; i <= max_index; i++)); do filename=`basename "${files[i]}"` #Подготавливаем строчку для меню dialog_array="$dialog_array $i $filename " done #Отоброжаем меню $DIALOG --menu "Select backup to restore" 30 60 30 $dialog_array 2> $temp_file #Читаем ответ answer=`cat $temp_file` #Если ничего не выбранно - выходим из программы. if [ -z $answer ];then clear exit fi #Отоброжаем меню yes/no $DIALOG --yesno "Do you really want to restore ${files[$answer]}?" 10 70 case $? in 0) #Устанавливаем метку backupRestore="_before_restore" #Делаем резервную копию текущей конфигурации backup $conf #Восстанавливаем файл cp ${files[$answer]} $pathToConf$configName;; 1) exit;; 255) exit;; esac } function restore_last { $DIALOG --yesno "Do you really want to restore all backup files?" 10 70 case $? in 0) #Устанавливаем метку backupRestore="_before_mass_restore" #Делаем резервную копию backup #Перебираем все конфиги for ((i = 0; i <= number; i++)); do paths $i backupname=`ls -t -1 $pathToBack$configName_* | head --lines 1` cp $backupname $pathToConf$configName done;; 1) exit;; 255) exit;; esac } #Функция вывода конфигов на экран function list_config { echo "Configs to backup: " for ((i = 0; i <= number; i++)); do echo ${pathToConfig[$i]}; done } #Функция показывает как работать с программой function usage { echo "Backup/Restore Config by nol1ght v1.0" echo "Usage:" echo "-b backup config" echo "-l list of configs" echo "-r restore config" echo "-rl restore all last configs" echo "-help this message" } #Проверяем под рутом ли мы зашли if [ "$(id -u)" != "0" ]; then echo "This script must be run as root" 1>&2 exit 1 fi #Загружаем конфиги read_config #переключаемся по пунку меню case $1 in -b) backup;; -r) restore;; -rl) restore_last;; -l) list_config;; --help) usage;; esac clear exit
Файл bconf_config имеет следующую структуру:
Путь_до_конфига Разделитель Путь_до_каталога_хранения
К примеру:
/etc/apache2/apache2.conf;/home/nol1ght/backup/apache2/ /etc/php5/apache2/php.ini;/home/nol1ght/backup/php/
Всё теперь осталось поставить в крон, я ставлю на раз в час
0 * * * * /home/nol1ght/bconf -b
Скриншоты процесса восстановления в dialog и gdialog:
Берегите Ваши конфиги и меньше их восстанавливайте :)
Комментариев нет:
Отправить комментарий