ad.backup.zfs
2026-05-17
ad.backup.zfs/lib/main.sh
.. init . По сути архивация имеющегося самопиского решания для памяти.
| awgur@0 | 1 #!/bin/sh |
| awgur@0 | 2 # devel.a0fs.net: zfsbackup.lib.log - v0.1 by awgur |
| awgur@0 | 3 # --- |
| awgur@0 | 4 # Файл содержит процедуры и функции организации определения и исполнения |
| awgur@0 | 5 # заданий на резервное копирование наборов данных ZFS |
| awgur@0 | 6 |
| awgur@0 | 7 # Определяем корень иерархии файлов относительно файла задания $dir_root/task/$task_name |
| awgur@0 | 8 # при условии что данная переменная не определена в вызывающем скрипте |
| awgur@0 | 9 dir_root="${dir_root:-$(dirname "$(dirname "$(readlink -f "$0")")")}" |
| awgur@0 | 10 dir_lib="${dir_lib:-${dir_root}/lib}" # Директория с библиотеками |
| awgur@0 | 11 |
| awgur@0 | 12 . "${dir_lib}/log.sh" |
| awgur@0 | 13 |
| awgur@0 | 14 sys_propNamePrefix="net.a0fs.zfsbackup" # префикс для свойств набора данных ZFS, |
| awgur@0 | 15 # в которые будут сохранятся параметры |
| awgur@0 | 16 |
| awgur@0 | 17 sys_backupType_d="daily" |
| awgur@0 | 18 sys_backupType_h="hourly" |
| awgur@0 | 19 sys_date_now="$(date '+%Y%m%d-%H%M%S')" |
| awgur@0 | 20 sys_date_today="$(date '+%Y%m%d')" |
| awgur@0 | 21 sys_date_thisHour="$(date '+%Y%m%d-%H')" |
| awgur@0 | 22 |
| awgur@0 | 23 svc_isNum () { |
| awgur@0 | 24 # Проверяет, является ли аргумент числом |
| awgur@0 | 25 echo "$1" | grep -vE '^[[:space:]]*$' | sed 's/[[:space:]]//g' | tr -d '\n\r' | grep -E '^[0-9]+$' > /dev/null 2>&1 |
| awgur@0 | 26 } |
| awgur@0 | 27 |
| awgur@0 | 28 svc_makeName () { |
| awgur@0 | 29 # Конструктор имени снимка. Для однотипного именования по всему скрипту |
| awgur@0 | 30 # Аргументы: |
| awgur@0 | 31 # dataset_name : Имя набора данных, для которого получаем снимок |
| awgur@0 | 32 # backup_type : Имя типа резервного копирования |
| awgur@0 | 33 # timeMark : Метка времени |
| awgur@0 | 34 if ! [ "$1" -a "$2" -a "$3" ] ; then |
| awgur@0 | 35 log_err "svc_makeName(): Not enough arguments (dataset_name='$1', backup_type='$2', timeMark='$3')" |
| awgur@0 | 36 return 1 |
| awgur@0 | 37 fi |
| awgur@0 | 38 echo "$1@${sys_propNamePrefix}_${3}_${2}" |
| awgur@0 | 39 } |
| awgur@0 | 40 |
| awgur@0 | 41 svc_date_getSnapTime () { |
| awgur@0 | 42 # Получение временной метки из имени снимка |
| awgur@0 | 43 local buf |
| awgur@0 | 44 if ! [ "$1" ] ; then |
| awgur@0 | 45 return 1 |
| awgur@0 | 46 fi |
| awgur@0 | 47 |
| awgur@0 | 48 echo "$1" | sed "s/.*@${sys_propNamePrefix}_//" | cut -f 1 -d '_' |
| awgur@0 | 49 } |
| awgur@0 | 50 |
| awgur@0 | 51 svc_date_isToday () { |
| awgur@0 | 52 # Проверка, сделан ли снимок набора данных в день проверки |
| awgur@0 | 53 local buf |
| awgur@0 | 54 if ! [ "$1" ] ; then |
| awgur@0 | 55 return 1 |
| awgur@0 | 56 fi |
| awgur@0 | 57 |
| awgur@0 | 58 svc_date_getSnapTime "$1" | grep -E "^${sys_date_today}" >/dev/null 2>&1 |
| awgur@0 | 59 } |
| awgur@0 | 60 |
| awgur@0 | 61 svc_date_isThisHour () { |
| awgur@0 | 62 # Проверка, сделан ли снимок набора данных в час проверки |
| awgur@0 | 63 local buf |
| awgur@0 | 64 if ! [ "$1" ] ; then |
| awgur@0 | 65 return 1 |
| awgur@0 | 66 fi |
| awgur@0 | 67 |
| awgur@0 | 68 svc_date_getSnapTime "$1" | grep -E "^${sys_date_thisHour}" >/dev/null 2>&1 |
| awgur@0 | 69 } |
| awgur@0 | 70 |
| awgur@0 | 71 zfs_getSnaps () { |
| awgur@0 | 72 # Получить список снимков для данного в аргументах набора. |
| awgur@0 | 73 # ВНИМАНИЕ! Снимки сортируются в обратном порядке |
| awgur@0 | 74 # Аргументы: |
| awgur@0 | 75 # dataset_name : Имя набора, для которго получаем снимки |
| awgur@0 | 76 # backup_type : Имя типа резервного копирования |
| awgur@0 | 77 if ! [ "$1" -a "$2" ] ; then |
| awgur@0 | 78 log_err "zfs_getSnaps(): Dataset or backup type not set: dataset='$1' backup_type='$2'" |
| awgur@0 | 79 return 1 |
| awgur@0 | 80 fi |
| awgur@0 | 81 |
| awgur@0 | 82 zfs list -Ho name -d 1 -r -t snapshot "$1" \ |
| awgur@0 | 83 | grep -E "@${sys_propNamePrefix}_[0-9]{8}-[0-9]{6}_${2}\$" \ |
| awgur@0 | 84 | sort -r |
| awgur@0 | 85 } |
| awgur@0 | 86 |
| awgur@0 | 87 zfs_getLastSnap () { |
| awgur@0 | 88 # Получить последний снимок созданный системой резервного копирования |
| awgur@0 | 89 # Аргументы: |
| awgur@0 | 90 # dataset_name : Имя набора, для которого получаем снимок |
| awgur@0 | 91 if ! [ "$1" ] ; then |
| awgur@0 | 92 log_err "zfs_getLastSnap(): Dataset not set" |
| awgur@0 | 93 return 1 |
| awgur@0 | 94 fi |
| awgur@0 | 95 |
| awgur@0 | 96 zfs list -Ho name -d 1 -r -t snapshot "$1" \ |
| awgur@0 | 97 | grep -E "@${sys_propNamePrefix}_[0-9]{8}-[0-9]{6}_" \ |
| awgur@0 | 98 | sort -r | head -n 1 |
| awgur@0 | 99 } |
| awgur@0 | 100 |
| awgur@0 | 101 zfs_getProp () { |
| awgur@0 | 102 # Получить значение свойства из zfs, относящиеся к системе резервного копирования |
| awgur@0 | 103 # Аргументы: |
| awgur@0 | 104 # dataset_name : Имя набора данных |
| awgur@0 | 105 # prop_name : Имя свойства |
| awgur@0 | 106 local res |
| awgur@0 | 107 |
| awgur@0 | 108 if ! [ "$1" -a "$2" ] ; then |
| awgur@0 | 109 return 1 |
| awgur@0 | 110 fi |
| awgur@0 | 111 res=$(zfs get -Hp -o value "${sys_propNamePrefix}:$2" "$1") |
| awgur@0 | 112 |
| awgur@0 | 113 if [ "${res}" = "-" ] ; then |
| awgur@0 | 114 res="" |
| awgur@0 | 115 fi |
| awgur@0 | 116 echo "$res" |
| awgur@0 | 117 } |
| awgur@0 | 118 |
| awgur@0 | 119 zfs_setProp () { |
| awgur@0 | 120 # Установить значение свойства в zfs, относящиеся к системе резервного копирования |
| awgur@0 | 121 # Аргументы: |
| awgur@0 | 122 # dataset_name : Имя набора данных |
| awgur@0 | 123 # prop_name : Имя свойства |
| awgur@0 | 124 # prop_value : Значение свойства |
| awgur@0 | 125 if ! [ "$1" -a "$2" -a "$3" ] ; then |
| awgur@0 | 126 return 1 |
| awgur@0 | 127 fi |
| awgur@0 | 128 |
| awgur@0 | 129 zfs set "${sys_propNamePrefix}:$2"="$3" "$1" |
| awgur@0 | 130 log "zfs_setProp(): Property changed for '$1': user='$(whoami 2>/dev/null)' uid='$(id -u)' property='$2' value='$3'" |
| awgur@0 | 131 } |
| awgur@0 | 132 |
| awgur@0 | 133 zfs_isBackup () { |
| awgur@0 | 134 # Необходимо ли резервное копирование для данного набора данных |
| awgur@0 | 135 # Аргументы: |
| awgur@0 | 136 # dataset_name : Имя исследуемого набора данных |
| awgur@0 | 137 case "$(zfs_getProp "$1" "enable")" in |
| awgur@0 | 138 yes|y ) |
| awgur@0 | 139 return 0 |
| awgur@0 | 140 ;; |
| awgur@0 | 141 * ) |
| awgur@0 | 142 return 1 |
| awgur@0 | 143 ;; |
| awgur@0 | 144 esac |
| awgur@0 | 145 } |
| awgur@0 | 146 |
| awgur@0 | 147 zfs_clean () { |
| awgur@0 | 148 # Удаление устаревших резервных копий |
| awgur@0 | 149 # Аргументы: |
| awgur@0 | 150 # dataset_name : Набор данных для которого производится операция |
| awgur@0 | 151 # backup_type : Тип резервной копии |
| awgur@0 | 152 # count : Количество копий, которые необходимо сохранить |
| awgur@0 | 153 local cnt |
| awgur@0 | 154 |
| awgur@0 | 155 if ! svc_isNum "$3" ; then |
| awgur@0 | 156 log_err "zfs_clean(): Wrong backup count: %3 (dataset_name='$1', backup_type='$2')" |
| awgur@0 | 157 return 1 |
| awgur@0 | 158 fi |
| awgur@0 | 159 cnt="$(( $cnt + 1 ))" |
| awgur@0 | 160 |
| awgur@0 | 161 zfs_getSnaps "$1" "$2" \ |
| awgur@0 | 162 | tail -n "+${cnt}" | xargs -n 1 zfs destroy -v \ |
| awgur@0 | 163 | awk "{print \"$1: \" \$0 }" | log |
| awgur@0 | 164 } |