Link Here
|
|
|
1 |
--- etc/periodic/zfs-snapshot.orig 2016-01-05 01:44:44.000000000 +0100 |
2 |
+++ etc/periodic/zfs-snapshot 2021-03-27 00:23:26.179216000 +0000 |
3 |
@@ -3,6 +3,7 @@ |
4 |
# take the appropriately named snapshot |
5 |
create_snapshot() |
6 |
{ |
7 |
+ local _skip _inherited |
8 |
pool=$1 |
9 |
|
10 |
case "$type" in |
11 |
@@ -28,7 +29,7 @@ |
12 |
|
13 |
# enumerate datasets under this pool or dataset, skip excluded datasets if requested |
14 |
if [ -n "$skip" ]; then |
15 |
- egrep="($(echo $skip | sed "s/ /|/g"))" |
16 |
+ egrep="($(echo $skip | sed -E "s/[[:blank:]]+/|/g"))" |
17 |
datasets=$(zfs list -r -H -o name $pool | egrep -v "$egrep") |
18 |
else |
19 |
datasets=$(zfs list -r -H -o name $pool) |
20 |
@@ -36,9 +37,41 @@ |
21 |
|
22 |
# loop through datasets, do snapshots of each |
23 |
for dataset in $datasets; do |
24 |
+ # skip datasets with mountpoint property set to "none", these usually |
25 |
+ # don't contain data but are used for properties inheritance only. |
26 |
+ if zfs get -H -o value mountpoint $dataset 2>/dev/null | grep -q "^none" |
27 |
+ then |
28 |
+ echo " mountpoint property of $dataset is "none", skipping..." |
29 |
+ continue |
30 |
+ fi |
31 |
+ _skip=$(zfs get -H -o value periodic:skip $dataset 2>/dev/null \ |
32 |
+ | tr '[:blank:]' ',') |
33 |
+ # check current dataset for user property periodic:skip |
34 |
+ if [ X${_skip} != X- ]; then |
35 |
+ _inherited="$(zfs get -H -o source periodic:skip $dataset 2>/dev/null\ |
36 |
+ | grep -o "^inherited")" |
37 |
+ # values of al(l|ways), true, 1, on, always, yes indicate that |
38 |
+ # no snapshot is wanted - for children aswell - and indipendent of |
39 |
+ # $type, while $type match does only exclude for the current type. |
40 |
+ if echo ${_skip} | grep -qiE "(^|,)$type"; then |
41 |
+ echo -n " periodic:skip property of $dataset" |
42 |
+ echo " ${_inherited:-matches} \"$type\", skipping..." |
43 |
+ continue |
44 |
+ elif echo ${_skip} | grep -qiE -e "^(al|true|1|on|yes)"; then |
45 |
+ echo -n " periodic:skip property of $dataset" |
46 |
+ echo " ${_inherited:-matches} \"$_skip\", skipping..." |
47 |
+ continue |
48 |
+ fi |
49 |
+ elif [ X${_skip} != X${_skip#base*} ] && [ -z "${_inherited}" ]; then |
50 |
+ # value of "base" has to be ignored if user property was inherited, |
51 |
+ # otherwise skip current dataset indipendently of $type |
52 |
+ echo -n " periodic:skip property of $dataset matches" |
53 |
+ echo " \"base\", skipping..." |
54 |
+ continue |
55 |
+ fi |
56 |
snapshot="$dataset@$now" |
57 |
# look for an existing snapshot with this name |
58 |
- if zfs list $snapshot > /dev/null 2>&1; then |
59 |
+ if [ -n "$(zfs list -H -o name $snapshot 2>/dev/null)" ]; then |
60 |
echo " snapshot $snapshot already exists, skipping..." |
61 |
else |
62 |
echo " taking snapshot: $snapshot" |
63 |
@@ -51,12 +84,7 @@ |
64 |
delete_snapshot() |
65 |
{ |
66 |
snapshot=$1 |
67 |
- echo " destroying old snapshot, $snapshot" |
68 |
- if ! echo $snapshot | grep -q @; then |
69 |
- # refuse to destroy something that doesn't look like a snapshot |
70 |
- echo >&2 " aborting: not a snapshot: $snapshot" |
71 |
- exit 1 |
72 |
- fi |
73 |
+ echo " destroying old snapshot, $snapshot" |
74 |
zfs destroy -r $snapshot |
75 |
} |
76 |
|
77 |
@@ -68,55 +96,65 @@ |
78 |
type=$3 |
79 |
skip=$4 |
80 |
|
81 |
- # create the regex matching the type of snapshots we're currently working |
82 |
- # on |
83 |
- case "$type" in |
84 |
- hourly) |
85 |
- # hourly-2009-01-01-00 |
86 |
- regex="^$pool@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]$" |
87 |
- ;; |
88 |
- daily) |
89 |
- # daily-2009-01-01 |
90 |
- regex="^$pool@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$" |
91 |
- ;; |
92 |
- weekly) |
93 |
- # weekly-2009-01 |
94 |
- regex="^$pool@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]" |
95 |
- ;; |
96 |
- monthly) |
97 |
- # monthly-2009-01 |
98 |
- regex="^$pool@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]" |
99 |
- ;; |
100 |
- yearly) |
101 |
- # yearly-2009 |
102 |
- regex="^$pool@$type-[0-9][0-9][0-9][0-9]" |
103 |
- ;; |
104 |
- *) |
105 |
- echo "unknown snapshot type: $type" |
106 |
- exit 1 |
107 |
- esac |
108 |
- |
109 |
create_snapshot $pool $type |
110 |
+ clean_snapshots $pool $type |
111 |
+} |
112 |
|
113 |
- # get a list of all of the snapshots of this type sorted alpha, which |
114 |
- # effectively is increasing date/time |
115 |
- # (using sort as zfs's sort seems to have bugs) |
116 |
- snapshots=`zfs list -H -o name -t snapshot | sort | grep $regex` |
117 |
- # count them |
118 |
- count=`echo $snapshots | wc -w` |
119 |
- if [ $count -ge 0 ]; then |
120 |
- # how many items should we delete |
121 |
- delete=`expr $count - $keep` |
122 |
- count=0 |
123 |
- # walk through the snapshots, deleting them until we've trimmed deleted |
124 |
- for snapshot in $snapshots; do |
125 |
- if [ $count -ge $delete ]; then |
126 |
- break |
127 |
- fi |
128 |
- delete_snapshot $snapshot |
129 |
- count=`expr $count + 1` |
130 |
- done |
131 |
- fi |
132 |
+clean_snapshots() |
133 |
+{ |
134 |
+ pool=$1 |
135 |
+ |
136 |
+ # loop through datasets, do look for number of snapshots each |
137 |
+ for dataset in $datasets; do |
138 |
+ |
139 |
+ # create the regex matching the type of snapshots we're currently working |
140 |
+ # on |
141 |
+ case "$type" in |
142 |
+ hourly) |
143 |
+ # hourly-2009-01-01-00 |
144 |
+ regex="^$dataset@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]$" |
145 |
+ ;; |
146 |
+ daily) |
147 |
+ # daily-2009-01-01 |
148 |
+ regex="^$dataset@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$" |
149 |
+ ;; |
150 |
+ weekly) |
151 |
+ # weekly-2009-01 |
152 |
+ regex="^$dataset@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]" |
153 |
+ ;; |
154 |
+ monthly) |
155 |
+ # monthly-2009-01 |
156 |
+ regex="^$dataset@$type-[0-9][0-9][0-9][0-9]-[0-9][0-9]" |
157 |
+ ;; |
158 |
+ yearly) |
159 |
+ # yearly-2009 |
160 |
+ regex="^$dataset@$type-[0-9][0-9][0-9][0-9]" |
161 |
+ ;; |
162 |
+ *) |
163 |
+ echo "unknown snapshot type: $type" |
164 |
+ exit 1 |
165 |
+ esac |
166 |
+ |
167 |
+ # get a list of all of the snapshots of this type sorted alpha, which |
168 |
+ # effectively is increasing date/time |
169 |
+ # (using sort as zfs's sort seems to have bugs) |
170 |
+ snapshots=`zfs list -H -o name -t snapshot | sort | grep $regex` |
171 |
+ # count them |
172 |
+ count=`echo $snapshots | wc -w` |
173 |
+ if [ $count -ge 0 ]; then |
174 |
+ # how many items should we delete |
175 |
+ delete=`expr $count - $keep` |
176 |
+ count=0 |
177 |
+ # walk through the snapshots, deleting them until we've trimmed deleted |
178 |
+ for snapshot in $snapshots; do |
179 |
+ if [ $count -ge $delete ]; then |
180 |
+ break |
181 |
+ fi |
182 |
+ delete_snapshot $snapshot |
183 |
+ count=`expr $count + 1` |
184 |
+ done |
185 |
+ fi |
186 |
+ done |
187 |
} |
188 |
|
189 |
# take snapshots of type, for pools, keeping keep old ones, |
190 |
@@ -130,6 +168,12 @@ |
191 |
echo "" |
192 |
echo "Doing zfs $type snapshots:" |
193 |
for pool in $pools; do |
194 |
- do_pool $pool $keep $type "$skip" |
195 |
+ # Add top/parent dataset to $skip if pool is defiend with trailing / |
196 |
+ if [ "${pool%/}" != "${pool}" ]; then |
197 |
+ pool=${pool%/} |
198 |
+ do_pool $pool $keep $type "${pool}\$${skip:+ ${skip}}" |
199 |
+ else |
200 |
+ do_pool $pool $keep $type "$skip" |
201 |
+ fi |
202 |
done |
203 |
} |