Backup script своими руками

430 / 2

Здравствуй, мой маленький бородатый друг. Я хочу рассказать тебе как написать гибкий backup script, используя язык Bash. В рунете есть великое множество скриптов на любой вкус, но мне, к сожалению, ни один из них не понравился. Поэтому я решил написать свой собственный велосипед с костылями и ssh. Поехали!

Давайте вначале разложим всё по полочкам и сформулируем задание. Наш компьютер будет выступать в роли сервера и на него мы будем копировать данные с различных машин, которые находятся в нашей локальной сети. Сразу оговорюсь, что скрипт проверялся только на Unix-подобных системах, типа Ubuntu, Red Hat и Mac OS X. На винде не пробовал, да и нужно ли?

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

Идем дальше. Сделаем скрипт более гибким и дадим возможность выбирать какой бэкап сделать – full или incremental. И реализуем ротацию данных. Это значит, что каждому бэкапу будет присвоена папка с датой его выполнения, а устаревшие версии бэкапов будут удаляться.

Для написания скрипта я использовал встроенный язык Bash. Конечно, вы можете написать его и на Python, но возможностей командной оболочки вполне хватит для реализации подобного задания.

Начнём с ключей и основных параметров, которые мы будем вводить для запуска скрипта. Для этого используем встроенную утилитку getopts. Внимание, не путать с getopt! Getopts уже встроена в Bash, а getopt придётся вызывать извне.

#!/bin/bash
 #Start script with some variables for work
 while getopts "hb:d:c:i:l:p:j:u:" optname
 do
 case "$optname" in
 "h") echo "Some help for you, my friend:"; #-h will show help to user
 echo "--- -i - enter IP adress to connect via SSH;";
 echo "--- -u - enter username;";
 echo "--- -b - change full backup directory on your PC to save data";
 echo "--- -c - change incremental backup directory on your PC to save data";
 echo "--- -d - enter the directory u want to backup from machine";
 echo "--- -l - enter the name of your log file. it will be saved in /home/backups/fullbackup/";
 echo "--- -j - enter your email to send you error log";
 exit;;
"?") echo "Uknown key or you just miss the button. Try again.";
 exit;;
 "j") echo "your email is $OPTARG";
 MAIL=$OPTARG;;
 "l") echo "You have changed your logname file to /home/backups/fullbackup/$OPTARG";
 LOG=/home/backups/fullbackup/$OPTARG;;
 "b") echo "You have changed destination folder for your backup to /home/backups/fullbackup/$OPTARG";
 DES=/home/backups/fullbackup/$OPTARG;;
 "c") echo "You have changed destination folder for your incremental backup to /home/backups/incrbackup/$OPTARG";
 INCR=/home/backups/incrbackup/$OPTARG;;
 "u") echo "You will log to machine as $OPTARG";
 USR=$OPTARG;;
 "i") echo "IP has been changed to $OPTARG";
 IPADR=$OPTARG;;
 "d") echo "Directory what will be save is - $OPTARG";
 SOURCE=$OPTARG;;
 esac
 done

Задаем основные ключи, с которыми мы будем запускать наш backup-script. Этот способ мне показался достаточно удобным и компактным. А для тех, кто не понял, что делает optargs – оставляю ссылку, дабы избавить вас от мучительного поиска информации.

Для копирования информации будем использовать утилиту rsync. Утилита эта очень гибкая, у неё есть множество ключей и, соответственно, возможностей. Добавим немного интерактивности в программу, чтобы пользователь мог выбирать, какой бэкап он хочет сделать.

Заранее оговорюсь, что последний бэкап лежит в папке FULL (для полного бэкапа) или INCRNEW (для инкрементального). После завершения программы бэкапы копируются в папки FULLOLD и INCROLD соответственно и там проходят процедуру ротации.

#Using If-then-else structure to use full or incremental backup
echo "----------Do u want to start full backup? y/n----------"
read n
if [ "$n" = "y" ];
then
#STARTING FULL BACKUP
echo "-------------------$(date +%F_%R:%S) START FULL BACKUP" > $LOG
rm -rf /home/backups/fullbackup/FULL/* #remove previous full backup
rsync --exclude-from '/home/backups/exclude.txt' -progress --log-file=$LOG -azv -e ssh $USR@$IPADR:$SOURCE $DES

#Create folder with today's date full backup
d=`date +%d-%m-%Y`
mkdir /home/backups/fullbackup/FULLOLD/$d
#Copy files from FULL to FULLOLD after the backup ends
cp -r $DES /home/backups/fullbackup/FULLOLD/$d
fi
echo "----------Do u want to start incremental backup? y/n----------"
read M
if [ "$M" = "y" ];
then
#STARTING INCREMENTAL BACKUP
echo "-------------------$(date +%F_%R:%S) START INCREMENTAL BACKUP" > $LOG
rsync --exclude-from '/home/backups/exclude.txt' -progress --log-file=$LOG -auzv -e ssh $USR@$IPADR:$SOURCE $INCR

#Create folder with today's date incremental backup
d=`date +%d-%m-%Y`
mkdir /home/backups/incrbackup/INCROLD/$d
cp -r $INCR /home/backups/incrbackup/INCROLD/$d
fi

Ранее, ещё в getopts, мы указывали ключик -j, который будет задавать почту, куда будет отправляться лог-файл с ошибками. Отправку почты реализуем с помощью нехитрой утилиты mailx:

#Send Error Logfile to mailing adress
mailx -s "ERROR LOGFILE" $MAIL

Теперь напишем очень простой блок для ротации файлов. Допустим, мы уже месяц копируем файлы с разных машин в нашей сети и папки FULLOLD и INCROLD у нас занимают over 9000 ГБ, в зависимости от того, что и откуда вы копировали. Такое количество информации сильно захламит компьютер, поэтому ограничим количество бекапов до 5, а старые просто будут удаляться.

target_dir=/home/backups/fullbackup/FULLOLD/
limit=5

#starting rotation. leave only 5 last backups in FULLOLD directory
n=1
for i in `ls $target_dir -t`
do
if [ $n -gt $limit ]
then
rm -Rvf $target_dir/$i
fi
n=$(($n+1))
done

#Starting rotation for incremental backup. Leave only 5 last backups. Limit and limit1 - may vary.
target=/home/backups/incrbackup/INCROLD/
limit1=5
#starting script for incremental old backups
number=1
for k in `ls $target -t`
do
if [ $number -gt $limit1 ]
then
rm -Rvf $target/$k
fi
number=$(($number+1))
done

Теперь скрипт можем сохранить в директории /home под названием, например, backupscript и запустить его. Обратите внимание, какие ключи и для чего вы используете. В этом вам поможет ключик -h, который покажет вам, за что отвечает каждый параметр.

Обязательно нужно сделать файл backupscript исполняемым:

chmod +x /home/backupscript

После этого, создадим файл, в который будет выводиться STDERR:

touch /home/backups/error.log

Все, скрипт готов к запуску!

root# ./.backupscript 2>/home/backups/error.log -i 192.168.0.33 -d /home/core -u root -b FULL -c INCRNEW -l LOGFILE -j kulikov@root-nation.com

Стиль написания программы несколько аляповатый, но на отладку и приведение кода в презентабельный вид у меня просто не хватило времени. Если есть какие-то вопросы – смело обращайтесь.


РЕКОМЕНДУЕМ! СВЕЖЕЕ ВИДЕО НА НАШЕМ YOUTUBE-КАНАЛЕ:
  • Эээм.
    if [ “$M” = “y” ]; — это всегда будет true

    • Хотя нет, в баш так можно, видимо.