ad.backup.zfs
2026-05-17
ad.backup.zfs/lib/main.sh
.. init . По сути архивация имеющегося самопиского решания для памяти.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/lib/main.sh Sun May 17 17:44:29 2026 +0300 1.3 @@ -0,0 +1,164 @@ 1.4 +#!/bin/sh 1.5 +# devel.a0fs.net: zfsbackup.lib.log - v0.1 by awgur 1.6 +# --- 1.7 +# Файл содержит процедуры и функции организации определения и исполнения 1.8 +# заданий на резервное копирование наборов данных ZFS 1.9 + 1.10 +# Определяем корень иерархии файлов относительно файла задания $dir_root/task/$task_name 1.11 +# при условии что данная переменная не определена в вызывающем скрипте 1.12 +dir_root="${dir_root:-$(dirname "$(dirname "$(readlink -f "$0")")")}" 1.13 +dir_lib="${dir_lib:-${dir_root}/lib}" # Директория с библиотеками 1.14 + 1.15 +. "${dir_lib}/log.sh" 1.16 + 1.17 +sys_propNamePrefix="net.a0fs.zfsbackup" # префикс для свойств набора данных ZFS, 1.18 + # в которые будут сохранятся параметры 1.19 + 1.20 +sys_backupType_d="daily" 1.21 +sys_backupType_h="hourly" 1.22 +sys_date_now="$(date '+%Y%m%d-%H%M%S')" 1.23 +sys_date_today="$(date '+%Y%m%d')" 1.24 +sys_date_thisHour="$(date '+%Y%m%d-%H')" 1.25 + 1.26 +svc_isNum () { 1.27 + # Проверяет, является ли аргумент числом 1.28 + echo "$1" | grep -vE '^[[:space:]]*$' | sed 's/[[:space:]]//g' | tr -d '\n\r' | grep -E '^[0-9]+$' > /dev/null 2>&1 1.29 +} 1.30 + 1.31 +svc_makeName () { 1.32 + # Конструктор имени снимка. Для однотипного именования по всему скрипту 1.33 + # Аргументы: 1.34 + # dataset_name : Имя набора данных, для которого получаем снимок 1.35 + # backup_type : Имя типа резервного копирования 1.36 + # timeMark : Метка времени 1.37 + if ! [ "$1" -a "$2" -a "$3" ] ; then 1.38 + log_err "svc_makeName(): Not enough arguments (dataset_name='$1', backup_type='$2', timeMark='$3')" 1.39 + return 1 1.40 + fi 1.41 + echo "$1@${sys_propNamePrefix}_${3}_${2}" 1.42 +} 1.43 + 1.44 +svc_date_getSnapTime () { 1.45 + # Получение временной метки из имени снимка 1.46 + local buf 1.47 + if ! [ "$1" ] ; then 1.48 + return 1 1.49 + fi 1.50 + 1.51 + echo "$1" | sed "s/.*@${sys_propNamePrefix}_//" | cut -f 1 -d '_' 1.52 +} 1.53 + 1.54 +svc_date_isToday () { 1.55 + # Проверка, сделан ли снимок набора данных в день проверки 1.56 + local buf 1.57 + if ! [ "$1" ] ; then 1.58 + return 1 1.59 + fi 1.60 + 1.61 + svc_date_getSnapTime "$1" | grep -E "^${sys_date_today}" >/dev/null 2>&1 1.62 +} 1.63 + 1.64 +svc_date_isThisHour () { 1.65 + # Проверка, сделан ли снимок набора данных в час проверки 1.66 + local buf 1.67 + if ! [ "$1" ] ; then 1.68 + return 1 1.69 + fi 1.70 + 1.71 + svc_date_getSnapTime "$1" | grep -E "^${sys_date_thisHour}" >/dev/null 2>&1 1.72 +} 1.73 + 1.74 +zfs_getSnaps () { 1.75 + # Получить список снимков для данного в аргументах набора. 1.76 + # ВНИМАНИЕ! Снимки сортируются в обратном порядке 1.77 + # Аргументы: 1.78 + # dataset_name : Имя набора, для которго получаем снимки 1.79 + # backup_type : Имя типа резервного копирования 1.80 + if ! [ "$1" -a "$2" ] ; then 1.81 + log_err "zfs_getSnaps(): Dataset or backup type not set: dataset='$1' backup_type='$2'" 1.82 + return 1 1.83 + fi 1.84 + 1.85 + zfs list -Ho name -d 1 -r -t snapshot "$1" \ 1.86 + | grep -E "@${sys_propNamePrefix}_[0-9]{8}-[0-9]{6}_${2}\$" \ 1.87 + | sort -r 1.88 +} 1.89 + 1.90 +zfs_getLastSnap () { 1.91 + # Получить последний снимок созданный системой резервного копирования 1.92 + # Аргументы: 1.93 + # dataset_name : Имя набора, для которого получаем снимок 1.94 + if ! [ "$1" ] ; then 1.95 + log_err "zfs_getLastSnap(): Dataset not set" 1.96 + return 1 1.97 + fi 1.98 + 1.99 + zfs list -Ho name -d 1 -r -t snapshot "$1" \ 1.100 + | grep -E "@${sys_propNamePrefix}_[0-9]{8}-[0-9]{6}_" \ 1.101 + | sort -r | head -n 1 1.102 +} 1.103 + 1.104 +zfs_getProp () { 1.105 + # Получить значение свойства из zfs, относящиеся к системе резервного копирования 1.106 + # Аргументы: 1.107 + # dataset_name : Имя набора данных 1.108 + # prop_name : Имя свойства 1.109 + local res 1.110 + 1.111 + if ! [ "$1" -a "$2" ] ; then 1.112 + return 1 1.113 + fi 1.114 + res=$(zfs get -Hp -o value "${sys_propNamePrefix}:$2" "$1") 1.115 + 1.116 + if [ "${res}" = "-" ] ; then 1.117 + res="" 1.118 + fi 1.119 + echo "$res" 1.120 +} 1.121 + 1.122 +zfs_setProp () { 1.123 + # Установить значение свойства в zfs, относящиеся к системе резервного копирования 1.124 + # Аргументы: 1.125 + # dataset_name : Имя набора данных 1.126 + # prop_name : Имя свойства 1.127 + # prop_value : Значение свойства 1.128 + if ! [ "$1" -a "$2" -a "$3" ] ; then 1.129 + return 1 1.130 + fi 1.131 + 1.132 + zfs set "${sys_propNamePrefix}:$2"="$3" "$1" 1.133 + log "zfs_setProp(): Property changed for '$1': user='$(whoami 2>/dev/null)' uid='$(id -u)' property='$2' value='$3'" 1.134 +} 1.135 + 1.136 +zfs_isBackup () { 1.137 + # Необходимо ли резервное копирование для данного набора данных 1.138 + # Аргументы: 1.139 + # dataset_name : Имя исследуемого набора данных 1.140 + case "$(zfs_getProp "$1" "enable")" in 1.141 + yes|y ) 1.142 + return 0 1.143 + ;; 1.144 + * ) 1.145 + return 1 1.146 + ;; 1.147 + esac 1.148 +} 1.149 + 1.150 +zfs_clean () { 1.151 + # Удаление устаревших резервных копий 1.152 + # Аргументы: 1.153 + # dataset_name : Набор данных для которого производится операция 1.154 + # backup_type : Тип резервной копии 1.155 + # count : Количество копий, которые необходимо сохранить 1.156 + local cnt 1.157 + 1.158 + if ! svc_isNum "$3" ; then 1.159 + log_err "zfs_clean(): Wrong backup count: %3 (dataset_name='$1', backup_type='$2')" 1.160 + return 1 1.161 + fi 1.162 + cnt="$(( $cnt + 1 ))" 1.163 + 1.164 + zfs_getSnaps "$1" "$2" \ 1.165 + | tail -n "+${cnt}" | xargs -n 1 zfs destroy -v \ 1.166 + | awk "{print \"$1: \" \$0 }" | log 1.167 +}