Backup скрипт на bash архивиращ Линукс отдалечени машини и рутери Mikrotik

Rsync
OpenSSH
sshpass

Сигурни ли сте, че можете да въстановите всички важни данни след човешка грешка, кражба от служител, повреда на хардуер, вируси и други подобни ? Кога за последно архивирахте вашите данни, къде се намира архива и за колко време може да въстановите система си ? Все въпроси на които, често служителя в пострадалата фирма започва да чупи пръсти, да гледа в земята и да подритва камъче което не съществува !

Как работи rsync

На този етап в Unix системите rsync е най мощният инструмент за архивиране на данни. След тази кратка команда rsync има в буквалния смисъл хиляди опции и варианти за архивиране на данни. Нека започенм с най простия:

rsync --delete -az /home/samyil/music/ /home/samyil/backup/

Всички файлове от директорията music ще бъдат копирани в backup. След повторно използване на командата всички промени в music ще се случат и в backup като rsync няма да копира цялата директорията като обем отново а ще изпълни само промените. Тоест, ако в music имаме 1000 файла, изтрием един и добавим друг, rsync в backup ще направи същото без да докосва другите 999 файла. Същото ще се случи ако са хиляди директории с хиляди файлове. Сега надявам се започва да става ясно защо е толкова невероятен този инструмент !

Да предположим, че в основната директория music по някаква причина имаме промяна във файловете и искаме да ги въстановим. Тъй като те са 1000 на брой се предполага, че и обема и е твърде голям за да копираме по стандартния начин архивираните данни обратно. Процедурата по връщането на архивираните дани в основната директория е много проста – само разменяме местата на основната и архивиращата директория:

rsync --delete -az /home/samyil/backup/ /home/samyil/music/

В този сценарии директорията backup ще се копира в директорията music.

Както вече казах можем да използваме различни опци според нуждите ни:

rsync --bwlimit 10000 --progress --stats --delete -avzh /home/samyil/music/ /home/samyil/backup/

–bwlimit 10000 ограничава скороста (в случая е 1mb) ако по някаква причина не искаме да си тормозим хард диска или да не запълним капацитета на Интернет връзката ни (rsync може да архивира и през мрежа)
–progress В реално време ни показва копирането на файловете в проценти (ако файловете са големи е много удобно)
–stats след като приключи ще ни покаже много информация от рода на колко файла е проверил, колко обем е трансферирал и много други.
–delete изтрива в архивиращата директория всичко което вече не съществува в основната (има вариант в който може да не искате това)
-a архивира директориите
-v показва повече информация
-z компресира
-h информацията излиза в четим вариант за човека

Доста често има случаи в които в основната директория имаме други такива които не искаме да архивираме, за да изключим от архива трябва за използваме опцията –exclude.

rsync --delete -az --exclude=/home/samyil/music/new --exclude=/home/samyil/music/new2 /home/samyil/music/ /home/samyil/backup/

Каквото и да копираме в new и new2 те няма да се копират в backup.

Най сигурният backup на данни е на отдалечения машина, физически несвързана и по възможност на километри от източника на данни.

Rsync владее силата да архивира данни през мрежата, от и на отдалечена машина посредством протокола SSH. С това той се превръща в незаменимо средство за системния администратор който иска да прехврърли криптирани данни били те за архив или за друго.

rsync --delete --stats -avzh -e ssh root@192.168.100.2:/var/www /home/samyil/backup

В случая от отдалечената машина директорията /var/www ще се копира в локалната машина в /home/samyil/backup.

Тъй като в горния пример rsync работи в комбинация с ssh, ако не сте свързвали досега с отдалечената машина стандартно ще бъдете попитани ще приемете ли ключа на SSH.

samyil@desktop:~$ ssh root@192.168.100.2
The authenticity of host '192.168.100.2 (192.168.100.2)' can't be established.
ECDSA key fingerprint is SHA256:OSGw4kv6v+d1mnR/Oczf55aQ89giR6cAJVocUZpfEKI.
Are you sure you want to continue connecting (yes/no)?

Тази досада ще ни пречи в скрипта с който искаме да автоматизираме архивирането на много машини. Когато се изпълнява скрипта за първи път трябва да обиколим преди това всички с SSH и да и приемем ключовете. За да не се случва това ще добавим в скрипта опцията на SSH -o StrictHostKeyChecking=no която на практика изключва промта (yes/no)?

ужас, sshpass ми знае паролата

И така, стигнахме до момента в който можем да архивираме от отдалечена машина но все още не може да автоматизираме процеса защото “някой” трябва да ни пише паролата на отдалечената машина дори и след като премахнахме първоначалното (yes/no)?. За шок и ужас на паранойците по сигурноста ще инсталирам една много полезна програмка sshpass с която ще автоматизирам изцяло архивирането.

sudo apt-get install sshpass

И ще изпълня rsync със следните опции като този път ще добавя и различен порт на отдалечената машина за SSH.

sshpass -p mypassword rsync --delete --stats -avzh -e 'ssh -o StrictHostKeyChecking=no -p 4444' root@192.168.100.2:/var/www /home/samyil/backup

Вече сме почти готови за написването на скрипт който ще автоматизира архивирането на данни на отдалечени сървъри.

Надявам се е ясно, че скрипта по долу не е подходящ за архивиране на бази данни като MySQL и MariaDB, за тях имам следното решение Как да архивираме всички бази в MySQL/MariaDB в Ubuntu с bash скрипт което разбира се може да се комбинира в долния скрипт.

Автоматизираме със скрипт

Създаваме файл backup.sh, копираме следното съдържание в него, конфигурираме си го по нашите нужди и го правим изпълним със sudo chmod +x backup.sh !

#!/bin/bash
 
#
# Based backup remote linux servers and mikrotik routers
# Require rsync, ssh and sshpass
#
# Samuil Arsov <support@itservice-bg.net>
#
 
### Global conf ###
RSYNC="rsync --delete --stats -azh"
SSH="-o StrictHostKeyChecking=no"
LOG="/var/log/backup.log"
 
### Remote linux server config ###
host1() {
  PASS="password1";
  PORT="22";
  SOURCE="root@192.168.100.2:/";
  DEST="/home/samyil/hosting1";
  EXCLUDE="--exclude /dev --exclude /proc --exclude /sys \
  --exclude /tmp --exclude /run --exclude /mnt"
}
 
host2() {
  PASS="password2";
  PORT="2222";
  SOURCE="root@192.168.100.3:/";
  DEST="/home/samyil/hosting2";
  EXCLUDE="--exclude /dev --exclude /proc --exclude /sys \
  --exclude /tmp --exclude /run --exclude /mnt --exclude \
  /var/lib/libvirt --exclude /var/lib/lxcfs --exclude /var/lib/nagios3/"
}
 
### Remote Mikrotik router config ###
router1() {
  PASS="password3";
  PORT="4444";
  SOURCE="admin@192.168.100.1";
  NAME="Mikrotik1.txt";
  DEST="/home/samyil/mikrotik";
}
 
router2() {
  PASS="password4";
  PORT="8888";
  SOURCE="admin@192.168.100.254";
  NAME="Mikrotik2.txt";
  DEST="/home/samyil/mikrotik";
}
 
### Banner separated logging server/router ###
banner(){
  echo ""
  echo "----------------------------------------------------------------"
  echo "Source: $SOURCE Destination: $DEST"
}
 
### Rsync backup remote linux server ###
rsync_script() {
  if [ ! -d $DEST ]; then
  mkdir -p $DEST
  fi
  sshpass -p $PASS $RSYNC -e "ssh $SSH -p $PORT" $SOURCE $EXCLUDE $DEST
}
 
### Export configuration mikrotik routers ###
ssh_script() {
  if [ ! -d $DEST ]; then
  echo mkdir -p $DEST
  fi
  sshpass -p $PASS ssh $SSH -p $PORT $SOURCE 'export compact' > $DEST/$NAME
  echo "$(stat $DEST/$NAME)"
}
 
### show space backup dir ###
show_space() {
  df -ht ext4
}
 
case "$1" in
 
### Start all backup configuration ###
  start)
    exec &> $LOG
    host1; banner; rsync_script
    host2; banner; rsync_script
    router1; banner; ssh_script
    router2; banner; ssh_script
    mail -s "host.itservice-bg.net backup" robot@telehost.bg < $LOG
    ;;
 
### show space backup dir ###
  show)
    echo "------------------------------------------------"
    show_space
    echo "------------------------------------------------"
    host1; du -sh $DEST
    host2; du -sh $DEST
    ;;
 
### show last log ###
  log)
    echo "------------------------------------------------"
    echo "$(cat $LOG)"
    ;;
 
  *)
 
### Usage commands ###
    clear
    echo $"Usage: $0 {start|show|log}"
    exit 1
    ;;
  esac
exit 0
Съвсем логично е, че нашият скрипт за архивиране на данни трябва да бъде максимално прост, защото простите неща са по безотказни. Допълнителните функции са излишни защото са евентуална опасност от счупване на скрипта а шарените съобщения така или иначе няма да ги гледаме защото кода ще се изпълнява в background режим.

Нека да направим така, че скрипта да се изпълнява всяка сутрин в 6 часа сутринта автоматично без човешка намеса. За целта трябва да редактираме /etc/crontab като добавим следния ред:

0 6 * * * root /home/samyil/backup.sh

И рестартираме cron демона за да влязат настройките в сила:

sudo service cron restart

Кратки бележки

В по ранен вариант бях сложил в скрипта проверка дали порта на SSH е достъпен, и ако не е изполванете на rsync се подминава с exit 0. По късно обаче видях, че нямам нужда от това, така или иначе SSH логва, че няма достъп до този порт. Въпреки всичко кода отдолу е полезен и може да се използва за по разширешен вариант (за обяснителни събития например)

nc -w 1 -z $(echo $SOURCE | cut -d "@" -f 2) $PORT
  if [ "$?" -eq 1 ]; then
    echo "SSH port is disable"
  exit 0
fi

Фунцията rsync_script() започва така:

  if [ ! -d $DEST ]; then
    mkdir -p $DEST
  fi

Този код е нужен защото при добавяне на нова машина за архивиране rsync ще види, че няма такава директория и ще спре като изплюе грешка. Това ще е много неудобно ако сървърите които архивираме са повечко и трябва да създадем директорията с mkdir по точния път.


Mikrotik в RouterOS има една вълшебна команда export, нейното предназначение е да покаже цялата конфигурация на рутера в текстов вид.

На практика ако изпълним:

sshpass -p <passtherouter> ssh -p 4444 admin@192.168.100.1 'export compact' > Router.txt

ще получим конфигурацията от рутера на локалната ни машина в текстовия файл Router.txt Този текстов файл става дори по ценен от собствената система за архивиране на Mikrotik защото винаги можеш да си го отвориш, да си го разгледаш и да промениш нещо в конфигурацията преди да започнеш да въстановяваш както често се случва на практика.


echo "$(stat $DEST/$NAME)"

Има много Линукс администратори които не знаят за съществуването на командата stat, не че тя се ползва толкова често но ако ви се е случвало да търсите следи от взлом в Линукс машина след bash_history и auth_log това е програмата която дава супер ценната информация. Нека я изпълним и да видим какво ще ни покаже тя:

Размер и кога за последно е модифициран файла е информациата която искам да логна за да знам копирал ли съм конфигурацията на рутера Mikrotik.


exec &> $LOG

Създава колектор на събитията и започва да логва всичко в $LOG файла. След като се изпълни скрипта логнатите събития се изпращат на мейл с:

mail -s "host.itservice-bg.net backup" robot@telehost.bg < $LOG

Така всяка сутрин след 6 часа сутринта, след като се изпълни скрипта аз получавам пълен отчет на мейла си за архивирането на данните от сървърите и конфигурационните файлове от рутерите който ми служи и като индикатор за броя на файлове и обема на данни по сървърите.

Изпълняване на скрипта

Нека проследим какво се случва ако изпълним скрипта. В първия прозорец стартираме скрипта с командата sudo ./backup.sh start. Тъй като всичко се случва в background режим във втория прозорец изпълняваме ps axf | grep -v grep | grep rsync за да видим има ли такъв процес rsync и какво прави той. В третия прозорец с sudo tail -f /var/log/backup.log в реално време следим логовете които така или иначе след това ще получим на мейла си.

Както се вижда по долу отчета изпратен на мейла е доста подробен, брой на файлове (създадени, изтрити), обем на данни (получени, изпратени) както и тотал на всичко това. Чисто технически поглеждайки отчета само първия сървър е притежател на 829703 файла които се побират 472.91 гигабайта но при архивирането са копирани само 3.22 гигабайта. Всеки който чете това и е стигнал до тук му е ясно каква е разликата да се копират по мрежа 472.91 гигабайта или 3.22 гигабайта, както и натоварване на хард дисковете, процесорно време и не на последно място излишно натоварване на Интернет капацитета.

Leave a Reply

Your email address will not be published. Required fields are marked *