Skip to content

Commit 5c561ac

Browse files
author
Aaron Hurt
committed
multiple fixes and enhancements
* enable warning by default when trying to replicate root datasets * strip trailing slashes from dataset names * use printf for log messages as it's more consistent across platforms * update readme warning about root datasets
1 parent c6dc932 commit 5c561ac

File tree

2 files changed

+59
-28
lines changed

2 files changed

+59
-28
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ Warning
1010
Replicating a root dataset to a remote will rewrite the remote pool with forced replication. This script will create
1111
a true 1:1 copy of the source (local) dataset in the destination (remote) dataset as currently configured.
1212

13-
This configuration (```REPLICATE_SETS="zpoolone:zpooltwo"```) will result in ```zpooltwo``` being a 1:1 copy of ```zpoolone```
13+
The configuration ```REPLICATE_SETS="zpoolone:zpooltwo"``` will result in ```zpooltwo``` being a 1:1 copy of ```zpoolone```
1414
and may result in dataloss on ```zpooltwo```.
1515

16+
To replicate a root dataset safely to another pool consider this configuration: ```REPLICATE_SETS="zpoolone:zpooltwo/zpoolone"```
17+
18+
This will result in a 1:1 copy of ```zpoolone``` in a separate data set of ```zpooltwo``` and will not affect other datasets currently present on the destination.
19+
1620
To Use
1721
------
1822

@@ -26,6 +30,14 @@ Snippet of that section can be found below.
2630
## the local snap name will be used on the remote end
2731
REPLICATE_SETS="zpoolone/somefs:zpooltwo zpoolone/otherfs:zpooltwo"
2832

33+
## allow replication of root datasets - if you specify root
34+
## datasets above and do not toggle this setting the
35+
## script will generate a warning and skip replicating
36+
## root datasets
37+
## 0 - disable (default)
38+
## 1 - enable (do so at your own risk)
39+
ALLOW_ROOT_DATASETS=0
40+
2941
## option to recurrsively snapshot children of
3042
## all datasets listed above
3143
## 0 - disable (previous behavior)

zfs-replicate.sh

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@
44
##
55

66
## datasets to replicate - use zfs paths not mount points...
7-
## format is local_pool/local_fs:remote_pool
8-
## the local snap name will be used on the remote end
7+
## format is local_pool/local_fs:remote_pool or
8+
## local_pool/local_fs:remote_pool/remote_fs the local name
9+
## will be used on the remote end if not specified
910
REPLICATE_SETS="zpoolone/somefs:zpooltwo zpoolone/otherfs:zpooltwo"
1011

12+
## allow replication of root datasets - if you specify root
13+
## datasets above and do not toggle this setting the
14+
## script will generate a warning and skip replicating
15+
## root datasets
16+
## 0 - disable (default)
17+
## 1 - enable (use at your own risk)
18+
ALLOW_ROOT_DATASETS=0
19+
1120
## option to recurrsively snapshot children of
1221
## all datasets listed above
1322
## 0 - disable (previous behavior)
@@ -115,7 +124,7 @@ check_old_log() {
115124
let "index += 1"
116125
done
117126
## delete excess logs
118-
echo "deleting old logs: ${slogs[@]:${LOG_KEEP}} ..."
127+
printf "deleting old logs: %s ...\n" ${slogs[@]:${LOG_KEEP}}
119128
rm -rf ${slogs[@]:${LOG_KEEP}}
120129
fi
121130
}
@@ -124,12 +133,12 @@ check_old_log() {
124133
exit_clean() {
125134
## print errors
126135
if [ "${1}x" != "x" ] && [ ${1} != 0 ]; then
127-
echo "Last operation returned error code: ${1}"
136+
printf "Last operation returned error code: %s\n" ${1}
128137
fi
129138
## check log files
130139
check_old_log
131140
## always exit 0
132-
echo "Exiting..."
141+
printf "Exiting...\n"
133142
exit 0
134143
}
135144

@@ -143,21 +152,20 @@ check_lock () {
143152
local ps=$(ps auxww|grep $lpid|grep -v grep)
144153
if [ "${ps}x" != 'x' ]; then
145154
## looks like it's still running
146-
echo "ERROR: This script is already running as: $ps"
155+
printf "ERROR: This script is already running as: %s\n" ${ps}
147156
else
148157
## well the lockfile is there...stale?
149-
echo "ERROR: Lockfile exists: '${1}'"
150-
echo -n "However, the contents do not match any "
151-
echo "currently running process...stale lock?"
158+
printf "ERROR: Lockfile exists: %s\n" ${1}
159+
printf "However, the contents do not match any "
160+
printf "currently running process...stale lockfile?\n"
152161
fi
153162
## tell em what to do...
154-
echo -n "To run script please delete: "
155-
echo "'${1}'"
163+
printf "To run script please delete: %s\n" ${1}
156164
## compress log and exit...
157165
exit_clean
158166
else
159167
## well no lockfile..let's make a new one
160-
echo "Creating lockfile: ${1}"
168+
printf "Creating lockfile: %s\n" ${1}
161169
echo $$ > "${1}"
162170
fi
163171
}
@@ -166,7 +174,7 @@ check_lock () {
166174
clear_lock() {
167175
## delete lockfiles...and that's all we do here
168176
if [ -f "${1}" ]; then
169-
echo "Deleting lockfile: ${1}"
177+
printf "Deleting lockfile: %s\n" ${1}
170178
rm "${1}"
171179
fi
172180
}
@@ -179,7 +187,7 @@ check_remote() {
179187
$REMOTE_CHECK > /dev/null 2>&1
180188
## exit if above returned non-zero
181189
if [ $? != 0 ]; then
182-
echo "ERROR: Remote health check '$REMOTE_CHECK' failed!"
190+
printf "ERROR: Remote health check '%s' failed!\n" ${REMOTE_CHECK}
183191
exit_clean
184192
fi
185193
fi
@@ -196,7 +204,7 @@ do_send() {
196204
else
197205
sendargs="-R -I ${1}"
198206
fi
199-
echo "RUNNING: ${ZFS} send $sendargs ${2} | ${RECEIVE_PIPE} ${3}"
207+
printf "RUNNING: %s send %s %s | %s %s\n" ${ZFS} $sendargs ${2} ${RECEIVE_PIPE} ${3}
200208
${ZFS} send $sendargs ${2} | ${RECEIVE_PIPE} ${3}
201209
## clear lockfile
202210
clear_lock "${LOGBASE}/.send.lock"
@@ -210,9 +218,20 @@ do_snap() {
210218
local sname="autorep-${NAMETAG}"
211219
## generate snapshot list and cleanup old snapshots
212220
for foo in $REPLICATE_SETS; do
213-
## split dataset into local and remote parts
214-
local_set=$(echo $foo|cut -f1 -d:)
215-
remote_set=$(echo $foo|cut -f2 -d:)
221+
## split dataset into local and remote parts and trim trailing slashes
222+
local local_set=$(echo $foo|cut -f1 -d:|sed 's/\/*$//')
223+
local remote_set=$(echo $foo|cut -f2 -d:|sed 's/\/*$//')
224+
## check for root datasets
225+
if [ $ALLOW_ROOT_DATASETS -ne 1 ]; then
226+
if [ "${local_set}" == $(basename "${local_set}") ] && \
227+
[ "${remote_set}" == $(basename "${remote_set}") ]; then
228+
printf "WARNING: Replicating root datasets can lead to data loss.\n"
229+
printf "To allow root dataset replication and disable this warning "
230+
printf "set ALLOW_ROOT_DATASETS=1 in this script. Skipping: %s\n\n" ${foo}
231+
## skip this set
232+
continue
233+
fi
234+
fi
216235
## get current existing snapshots that look like
217236
## they were made by this script
218237
if [ $RECURSE_CHILDREN -ne 1 ]; then
@@ -232,8 +251,8 @@ do_snap() {
232251
if [ "${sn}" == "${local_set}@${sname}" ]; then
233252
## looks like it's here...we better kill it
234253
## this shouldn't happen normally
235-
echo "Destroying DUPLICATE snapshot ${local_set}@${sname}"
236-
$ZFS destroy ${local_set}@${sname}
254+
printf "Destroying DUPLICATE snapshot %s@%s\n" ${local_set} ${sname}
255+
$ZFS destroy ${local_set}@${sname}
237256
else
238257
## append this snap to an array
239258
snaps[$index]=$sn
@@ -254,14 +273,14 @@ do_snap() {
254273
while [ $scount -ge $SNAP_KEEP ]; do
255274
## snaps are sorted above by creation in
256275
## ascending order
257-
echo "Destroying OLD snapshot ${snaps[$index]}"
276+
printf "Destroying OLD snapshot %s\n" ${snaps[$index]}
258277
$ZFS destroy ${snaps[$index]}
259278
## decrease scount and increase index
260279
let "scount -= 1"; let "index += 1"
261280
done
262281
fi
263282
## come on already...make that snapshot
264-
echo "Creating ZFS snapshot ${local_set}@${sname}"
283+
printf "Creating ZFS snapshot %s@%s\n" ${local_set} ${sname}
265284
## check if we are supposed to be recurrsive
266285
if [ $RECURSE_CHILDREN -ne 1 ]; then
267286
$ZFS snapshot ${local_set}@${sname}
@@ -289,18 +308,18 @@ do_snap() {
289308
init() {
290309
## sanity check
291310
if [ $SNAP_KEEP -lt 2 ]; then
292-
echo "ERROR: You must keep at least 2 snaps for incremental sending."
293-
echo "Please check the setting of 'SNAP_KEEP' in the script."
311+
printf "ERROR: You must keep at least 2 snaps for incremental sending.\n"
312+
printf "Please check the setting of 'SNAP_KEEP' in the script.\n"
294313
exit_clean
295314
fi
296315
## check remote health
297-
echo "Checking remote system..."
316+
printf "Checking remote system...\n"
298317
check_remote
299318
## do snapshots and send
300-
echo "Creating snapshots..."
319+
printf "Creating snapshots...\n"
301320
do_snap
302321
## that's it...sending called from do_snap
303-
echo "Finished all operations for ..."
322+
printf "Finished all operations for ...\n"
304323
## show a nice message and exit...
305324
exit_clean
306325
}

0 commit comments

Comments
 (0)