Важное преимущество Linux, BSD и других никсов — наличие очень мощных базовых утилиты, с помощью которых можно автоматизировать многие необходимые задачи. В частности, ssh
, rsync
позволяют очень удобно и надёжно создавать, передавать (в том числе и за многие километры по интернету) и всячески управлять бэкапами, а с помощью архиваторов их можно и сжимать. Windows, к сожалению, не обладает таким функционалом «из коробки», да и сторонние решения не «из коробки» не всегда подходят по ряду параметров. Поэтому, логично организовать сервер резервных копий даже в Win-сети на основе Linux и стягивать на него в плановое время данные для бэкапа. Посмотрим, как это можно не слишком умудрённо сделать.
Будем изначально подходить наиболее экономным способом: с наименьшей конфигурацией исходных машин. Для этого монтируем нужную шару, делаем копию, размонтируем. Монтируем с помощью mkfs.cifs
из пакета cifs-utils
. Если на машину можно зайти анонимно, так и заходим, с помощью соответствующей опции
mount -t cifs //192.168.10.99/Data $data_dir -o user=guest,guest
Можно, конечно, добавить шару в fstab
и держать постоянно смонтированной, но это скорее излишне, поэтому будем её монтировать только на время бэкапа. Также, на случай возможных ошибок, выбираем директорию каждый раз новую в /tmp
, получить временную директорию можно
mktemp -d
Копию будем делать дифференциальную на основе жёстких ссылок. rsync
позволяет делать делать hard-linked
копии сам, на основе предыдущей копии, или их можно делать отдельно, а затем заменять новые файлы. Воспользуемся вторым способом: в случае обрыва бэкапа мы получим не обновлённый, но полный бэкап, который обновится в следующий раз. В первом случае его придётся загружать полностью, что не всегда разумно если канал тонкий.
С учётом всего вышеперечисленного пишем скрипт
#!/bin/sh softmkdir() { if [ ! -d "$1" ] ; then mkdir "$1" chmod 0750 "$1" fi } # SETTINGS host=`hostname -s` backup_dir=/backup/$host/data_rsync len=90 softmkdir "$backup_dir" tmpname=new tmp_dir="$backup_dir/$tmpname" zero_dir="$backup_dir/d`printf "%02d" 0`" prev_dir="$backup_dir/d`printf "%02d" 1`" last_dir="$backup_dir/d`printf "%02d" $len`" date=`date` echo "=================================" echo "Starting backup: $date." if [ -d "$zero_dir" ]; then echo "Rotating directories up to length of $len." # removing last directory if [ -d "$last_dir" ]; then rm -rf "$last_dir" fi # rotating for i in $(seq $len -1 0); do src="$backup_dir/d`printf "%02d" $i`" if [ -d "$src" ]; then mv "$src" "$backup_dir/d`printf "%02d" $(($i+1))`" fi done fi if [ ! -d "$tmp_dir" ] ; then if [ -d "$prev_dir" ] ; then echo "Found previous backup. Making hard-linked copy." cp -al "$prev_dir" "$tmp_dir" echo "Hard-linked copy done." test -d "$tmp_dir" && touch "$tmp_dir" else echo "Previous backup not found. Creating init backup." softmkdir "$tmp_dir" fi else echo "Found temporary directory (not finished last backup), resuming it." fi data_dir=`mktemp -d` mount -t cifs //192.168.10.24/Data $data_dir -o user=guest,guest echo "Starting rsync..." rsync -azK --delete --ignore-errors --stats --numeric-ids $1 $data_dir/ "$tmp_dir/Data" test -d "$tmp_dir" && touch "$tmp_dir" echo "Rsync done." # moving temporary to latest echo "Moving temporary dir name to normal backup name." mv "$tmp_dir" "$zero_dir" umount $data_dir rm -d $data_dir echo "Backup finished: $date." echo "=================================" echo ""
Проверяем, что всё работает корректно и добавляем в cron
.
Спасибо, отличная статья.