Важное преимущество 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.