Анализ данных. Выбор для датасетов. Проверка на существование снимков.
This commit is contained in:
parent
3725a5c4ee
commit
1024043ab2
185
backup_data.zsh
185
backup_data.zsh
@ -1,107 +1,158 @@
|
|||||||
#!/bin/zsh
|
#!/bin/zsh
|
||||||
|
|
||||||
|
backup_server="192.168.0.162" # Сервер для резервирования
|
||||||
|
inc_snapshot="manual-$(date +%Y%m%d)" # Новый создаваемый снисмок
|
||||||
|
|
||||||
|
echo -ne "Обработка аргументов...\033[0K\r"
|
||||||
|
|
||||||
|
if [[ $# == 1 ]]; then
|
||||||
|
backup_server=$1
|
||||||
|
fi
|
||||||
|
if [[ $# == 2 ]]; then
|
||||||
|
backup_server=$1
|
||||||
|
inc_snapshot=$2
|
||||||
|
fi
|
||||||
|
if [[ $# > 2 ]]; then
|
||||||
|
echo "Ожидается 0 или 2 аргумента: backup_server или ни одного для сервера по умолчанию: $backup_server"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
echo "Резервирование на $backup_server"
|
||||||
|
echo "Снимок файловой системы $inc_snapshot"
|
||||||
# --------- Собираем данные ----------
|
# --------- Собираем данные ----------
|
||||||
|
|
||||||
backup_server="192.168.0.162"
|
echo -ne "Собираю данные...\033[0K\r"
|
||||||
|
# Получить список датасетов на локальной машине
|
||||||
|
local_datasets=$(zfs list -o name | grep -v -e ix-app -e boot-pool -e system-data -e jails | grep /) # Отрезаем всё лишнее, отделяем нужные данные по 4 пробелам в выводе.
|
||||||
|
local_datasets=(${=local_datasets}) # Конвертирование в массив
|
||||||
|
# Получить список датасетов на удалённой машине
|
||||||
|
backup_datasets=$(ssh root@$backup_server zfs list -o name | grep -v -e ix-app -e boot-pool -e system-data -e jails | grep /) # Отрезаем всё лишнее, отделяем нужные данные по 4 пробелам в выводе.
|
||||||
|
backup_datasets=(${=backup_datasets}) # Конвертирование в массив
|
||||||
|
|
||||||
srcpool="main_pool/"
|
# Высчитать что на что резервировать
|
||||||
inc_snapshot="manual-$(date +%Y%m%d)"
|
declare -A work_datasets
|
||||||
|
for ((i = 1; i <= ${#local_datasets}; i++)); do
|
||||||
# Словарь, содержащий списки резервируемых датасетов
|
for ((j = 1; j <= ${#backup_datasets}; j++)); do
|
||||||
declare -A datasets
|
a=$(sed -r "s/(.*)\/(.*)/\2/" <<<"$local_datasets[i]") # Определить нижний по иерархии
|
||||||
# ["${srcpool}3D_Design"]="NOD/Backup/3D_Design"
|
b=$(sed -r "s/(.*)\/(.*)/\2/" <<<"$backup_datasets[j]") # тоже дял второго
|
||||||
# ["${srcpool}Backups"]="NOD/Backup/Backups"
|
if [[ "$a" == "$b" ]]; then
|
||||||
# ["${srcpool}Documents"]="NOD/Backup/Documents"
|
work_datasets[${local_datasets[i]}]=${backup_datasets[j]}
|
||||||
# ["${srcpool}Family"]="NOD/Backup/Family"
|
|
||||||
# ["${srcpool}FTP_users"]="NOD/Backup/FTP_users"
|
|
||||||
datasets=(
|
|
||||||
["${srcpool}Media"]="NOD/Backup/Media"
|
|
||||||
["${srcpool}NOD/GenShtab"]="NOD/GenShtab"
|
|
||||||
["${srcpool}NOD/MinDiz"]="NOD/MinDiz"
|
|
||||||
["${srcpool}NOD/nod34"]="NOD/nod34"
|
|
||||||
["${srcpool}NOD/nod34_secret"]="NOD/nod34_secret"
|
|
||||||
["${srcpool}PhotoWork"]="NOD/Backup/PhotoWork"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Словарь со списком последких снапшотов для датасетов
|
|
||||||
declare -A last_local_snaps
|
|
||||||
declare -A last_backup_snaps
|
|
||||||
pre_snapshots=()
|
|
||||||
for ds in ${(k)datasets}; do
|
|
||||||
tmp="$(zfs list -r -t snapshot -H -o name ${srcpool::-1} | grep ${ds} | grep "manual" | egrep -o '@.+' | tail -n1)"
|
|
||||||
tmp=${tmp:1}
|
|
||||||
if [ "$tmp" = "$inc_snapshot" ]; then
|
|
||||||
read "del_snapshot?Датасет $ds уже имеет последний снимок $inc_snapshot. Удалить? (y/N)"
|
|
||||||
if [ "$del_snapshot" = "y" ]; then
|
|
||||||
zfs destroy "${ds}@${tmp}"
|
|
||||||
tmp="$(zfs list -r -t snapshot -H -o name ${srcpool::-1} | grep ${ds} | grep "manual" | egrep -o '@.+' | tail -n1)"
|
|
||||||
pre_snapshots[$ds]="${tmp:1}"
|
|
||||||
else
|
|
||||||
# Если не удалять, то просто исключить из резервирования
|
|
||||||
unset "datasets[$ds]"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
pre_snapshots[$ds]=$tmp
|
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Словарь со списком последких снапшотов для датасетов
|
||||||
|
declare -A last_loc_snaps
|
||||||
|
declare -A last_bak_snaps
|
||||||
|
echo -ne "Проверяю на наличие $inc_snapshot...\033[0K\r"
|
||||||
|
for loc_ds bak_ds in ${(kv)work_datasets}; do
|
||||||
|
# Запросить последние снимки
|
||||||
|
loc_snap="$(zfs list -t snapshot -o name ${loc_ds} | grep "manual" | tail -n1 | egrep -o '@.+' )"
|
||||||
|
loc_snap=${loc_snap:1} # удалить @ в начале строки
|
||||||
|
bak_snap="$(ssh root@$backup_server zfs list -t snapshot -o name ${bak_ds} | grep "manual" | tail -n1 | egrep -o '@.+' )"
|
||||||
|
bak_snap=${bak_snap:1} # удалить @ в начале строки
|
||||||
|
|
||||||
|
# Если последний снимок совпадает с сегодняшним
|
||||||
|
if [[ "$loc_snap" = "$inc_snapshot" ]]; then
|
||||||
|
# Если последние снимки на обеих машинах совпадают
|
||||||
|
if [[ "$loc_snap" = "$bak_snap" ]]; then
|
||||||
|
echo "${loc_ds}@${loc_snap} существует на обеих машинах. $loc_ds Исключено из списка"
|
||||||
|
unset "work_datasets[$loc_ds]"
|
||||||
|
else
|
||||||
|
# Если на удалённой машине нет такого снимка, то предложить удалить.
|
||||||
|
read "del_snapshot?Датасет $loc_ds уже имеет последний снимок $inc_snapshot. Удалить? (y/N)"
|
||||||
|
if [ "$del_snapshot" = "y" ]; then
|
||||||
|
zfs destroy "${loc_ds}@${loc_snap}"
|
||||||
|
loc_snap="$(zfs list -t snapshot -o name ${loc_ds} | grep "manual" | tail -n1 | egrep -o '@.+' )"
|
||||||
|
loc_snap="${loc_snap:1}"
|
||||||
|
last_loc_snaps[$loc_ds]=$loc_snap
|
||||||
|
# last_bak_snaps[$bak_ds]=$bak_snap # не нужно, нигде не используется
|
||||||
|
else
|
||||||
|
# Если не удалять, то просто исключить из резервирования
|
||||||
|
echo "$ds Исключено из списка"
|
||||||
|
unset "work_datasets[$ds]"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# добавить в список снапшотов
|
||||||
|
last_loc_snaps[$loc_ds]=$loc_snap
|
||||||
|
# last_bak_snaps[$bak_ds]=$bak_snap # не нужно, нигде не используется
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
# --------- Запрашиваем подтверждение пользователя ----------
|
# --------- Запрашиваем подтверждение пользователя ----------
|
||||||
|
|
||||||
echo
|
echo " "
|
||||||
echo "Резервирование на $backup_server"
|
|
||||||
echo "Список резервируемых датасетов:"
|
echo "Список резервируемых датасетов:"
|
||||||
for key in ${(k)datasets}; do
|
i=0; for loc_ds bak_ds in ${(kv)work_datasets}; do
|
||||||
echo "$key \t ${pre_snapshots[$key]} \t -> \t${datasets[$key]}"
|
i=$((i+1))
|
||||||
|
echo "$i - $loc_ds \t ${last_loc_snaps[$loc_ds]} \t -> \t${bak_ds}"
|
||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
echo "Инкрементный снимок:\t$inc_snapshot"
|
echo "Инкрементный снимок:\t$inc_snapshot"
|
||||||
|
|
||||||
read "work?Утвердите данные. Приступаем? (y/N) "
|
# --------- Выбор датасетов ----------
|
||||||
|
|
||||||
|
read "work?Утвердите данные. В работу (y), или перечислить через пробел номера, НЕТ по умолчанию? "
|
||||||
|
if [[ $work = *[[:digit:]]* ]]; then
|
||||||
|
indx_list=(${=work})
|
||||||
|
# Если нет индекса в списке, то удалить из словаря для резервирования
|
||||||
|
i=0; for loc_ds bak_ds in ${(kv)work_datasets}; do
|
||||||
|
i=$((i+1))
|
||||||
|
if [[ ${indx_list[(r)$i]} != $i ]]; then # Если нет $i в списке $indx_list
|
||||||
|
unset "work_datasets[$loc_ds]"
|
||||||
|
else
|
||||||
|
echo "$i - $loc_ds \t ${last_loc_snaps[$loc_ds]} \t -> \t${bak_ds}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Если был выведен список, то запросить запуск в работу нового списка
|
||||||
|
if [[ ${#indx_list} > 0 ]]; then
|
||||||
|
work="N"
|
||||||
|
read "work?В работу (y/N) "
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# --------- Резервирование ----------
|
# --------- Резервирование ----------
|
||||||
|
|
||||||
if [ "$work" = "y" ]
|
if [[ $work = "y" || $work = "Y" ]]; then
|
||||||
then
|
|
||||||
TS0=$(date +%s)
|
TS0=$(date +%s)
|
||||||
LOGFILE="log_${inc_snapshot}_backup.txt"
|
LOGFILE="log_${inc_snapshot}_backup.txt"
|
||||||
echo "Результат работы записываю в файл $LOGFILE"
|
echo "Результат работы записываю в файл $LOGFILE"
|
||||||
echo "Список резервируемых датасетов:" >> $LOGFILE
|
|
||||||
for key in ${(k)datasets}; do
|
# Записать в файл список резервируемых датасетов
|
||||||
echo "$key \t ${pre_snapshots[$key]} \t -> \t${datasets[$key]}" >> $LOGFILE
|
echo "Список резервируемых датасетов:" >> "${LOGFILE}"
|
||||||
|
for loc_ds in ${(k)work_datasets}; do
|
||||||
|
echo "$key \t ${last_loc_snaps[$loc_ds]} \t -> \t${work_datasets[$loc_ds]}" >> "${LOGFILE}"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo
|
echo
|
||||||
exec 6>&1 # Saves stdout
|
exec 6>&1 # Saves stdout
|
||||||
exec >> >(tee $LOGFILE) # stdout replaced with file
|
exec > >(tee $LOGFILE) # stdout replaced with file
|
||||||
|
|
||||||
echo "------------------------\nСоздаю снимки @${inc_snapshot}\n"
|
echo "\n--- Резервирую данные ---"
|
||||||
|
for loc_ds bak_ds in ${(kv)work_datasets}; do
|
||||||
TS1=$(date +%s)
|
TS1=$(date +%s)
|
||||||
for ds in ${(k)datasets}; do
|
echo " * snapshot ${loc_ds}@${inc_snapshot}"
|
||||||
echo " * ${ds}";
|
zfs snapshot ${loc_ds}@${inc_snapshot};
|
||||||
zfs snapshot ${ds}@${inc_snapshot};
|
echo " * Start sending ${loc_ds} at $(date +'%Y.%m.%d %H:%M.%S')"
|
||||||
done
|
zfs send -V -i ${loc_ds}@${last_loc_snaps[$loc_ds]} ${loc_ds}@${inc_snapshot} | ssh "root@${backup_server}" zfs receive ${bak_ds}@${inc_snapshot}
|
||||||
TS2=$(date +%s)
|
TS2=$(date +%s)
|
||||||
echo "Готово за: $(date -d@$(($TS2-$TS1)) -u +'%H:%M.%S')"
|
echo "Закончил ${loc_ds} за: $(date -d@$(($TS2-$TS1)) -u +%H:%M:%S)"
|
||||||
echo "------------------------\nРезервирую данные\n"
|
done & # Запустить резервирование в фоне
|
||||||
for ds in ${(k)datasets}; do
|
|
||||||
TS1=$(date +%s)
|
|
||||||
echo " * Start sending ${ds} at $(date +'%Y.%m.%d %H:%M.%S')"
|
|
||||||
zfs send -V -i ${ds}@${pre_snapshots[$ds]} ${ds}@${inc_snapshot} | ssh "root@${backup_server}" zfs receive ${datasets[$ds]}@${inc_snapshot}
|
|
||||||
TS2=$(date +%s)
|
|
||||||
echo "Закончил ${ds} за: $(date -d@$(($TS2-$TS1)) -u +%H:%M:%S)"
|
|
||||||
done &
|
|
||||||
exec 1>&6 6>&-
|
exec 1>&6 6>&-
|
||||||
|
|
||||||
|
# Выводить прогресс запрашивая список запущенныйх процессов
|
||||||
while pgrep -u $USER zfs >/dev/null; do
|
while pgrep -u $USER zfs >/dev/null; do
|
||||||
PROGR=$(ps -u | grep "send" | grep -v "grep" | sed -r "s/(.*) zfs: (.*)/\2/")
|
PROGR=$(ps -u | grep "send" | grep -v "grep" | sed -r "s/(.*) zfs: (.*)/\2/")
|
||||||
echo -ne "$PROGR\033[0K\r"
|
echo -ne "$PROGR\033[0K\r"
|
||||||
# echo -ne "$(ps -u | grep "send" | grep -v "grep" | sed -r "s/(.*) zfs: (.*)/\2/")\033[0K\r"
|
|
||||||
sleep 60
|
sleep 60
|
||||||
done
|
done
|
||||||
echo -e
|
echo -e
|
||||||
exec >> >(tee $LOGFILE)
|
exec > >(tee $LOGFILE)
|
||||||
echo "------------------------\nВсе завершено за $(date -d@$(($TS2-$TS0)) -u +%H:%M.%S)"
|
echo "\n---Все завершено за $(date -d@$(($TS2-$TS0)) -u +%H:%M.%S) ---"
|
||||||
|
|
||||||
exec 1>&6 6>&- # Restore stdout and close file descriptor #6.
|
exec 1>&6 6>&- # Restore stdout and close file descriptor #6.
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user