Здравствуй, мой маленький бородатый друг. Я хочу рассказать тебе как написать гибкий 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 [email protected]
Стиль написания программы несколько аляповатый, но на отладку и приведение кода в презентабельный вид у меня просто не хватило времени. Если есть какие-то вопросы – смело обращайтесь.
Эээм.
if [ “$M” = “y” ]; — это всегда будет true
Хотя нет, в баш так можно, видимо.