@@ -34,6 +34,11 @@ opt_keep=''
34
34
opt_label=' '
35
35
opt_prefix=' zfs-auto-snap'
36
36
opt_recursive=' '
37
+ opt_send_type=' '
38
+ opt_send_host=' '
39
+ opt_recv_pool=' '
40
+ opt_send_opts=' '
41
+ opt_recv_opts=' '
37
42
opt_sep=' _'
38
43
opt_setauto=' '
39
44
opt_syslog=' '
@@ -68,6 +73,8 @@ print_usage ()
68
73
-q, --quiet Suppress warnings and notices at the console.
69
74
--send-full=F Send zfs full backup. Unimplemented.
70
75
--send-incr=F Send zfs incremental backup. Unimplemented.
76
+ --send-opts=F Option(s) passed to 'zfs send'.
77
+ --recv-opts=F Option(s) passed to 'zfs receive'.
71
78
--sep=CHAR Use CHAR to separate date stamps in snapshot names.
72
79
-g, --syslog Write messages into the system log.
73
80
-r, --recursive Snapshot named filesystem and all descendants.
@@ -159,6 +166,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
159
166
# global WARNING_COUNT
160
167
# global SNAPSHOTS_OLD
161
168
169
+ SNAPS_DONE=' '
170
+
162
171
for ii in $TARGETS
163
172
do
164
173
if [ -n " $opt_do_snapshots " ]
@@ -170,6 +179,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
170
179
if [ $RUNSNAP -eq 1 ] && do_run " zfs snapshot $PROPS $FLAGS '$ii @$NAME '"
171
180
then
172
181
[ " $opt_post_snapshot " != " " ] && do_run " $opt_post_snapshot $ii $NAME "
182
+ [ -n " $opt_send_host " ] && SNAPS_DONE=" $SNAPS_DONE
183
+ $ii @$NAME "
173
184
SNAPSHOT_COUNT=$(( $SNAPSHOT_COUNT + 1 ))
174
185
else
175
186
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
@@ -203,6 +214,78 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
203
214
done
204
215
}
205
216
217
+ do_send () # snapname, oldglob
218
+ {
219
+ local NAME=" $1 "
220
+ local GLOB=" $2 "
221
+ local ii
222
+ local remote=" ssh $opt_send_host zfs receive $opt_recv_opts $opt_recv_pool "
223
+
224
+ # STEP 1: Go throug all snapshots we've created
225
+ for ii in $SNAPS_DONE
226
+ do
227
+ opts=' '
228
+ SNAPS_SEND=' '
229
+
230
+ dset=${ii%@* }
231
+
232
+ # STEP 2: Go through ALL snapshots that exist, look for exact
233
+ # match on dataset/volume (with snapshot matching 'GLOB').
234
+ for jj in $SNAPSHOTS_OLD
235
+ do
236
+ # Check whether this is an old snapshot of the filesystem.
237
+ if [ -z " ${jj# $dset @ $GLOB } " ]; then
238
+ # We want the FIRST one (which is the last in time
239
+ # before the one we just created in do_snapshot()).
240
+ # Also, here we just need the snapshot name.
241
+ last_snap=" ${jj#*@ } "
242
+ break
243
+ fi
244
+ done
245
+
246
+ # NOTE: If we don't have any previous snapshots (for example, we've
247
+ # just created the first one) we can end up with last_snap=''
248
+ # here.
249
+ # If we're called with '--send-incr' we have to options:
250
+ # 1: We change from incremental to full.
251
+ # 2: We accept that the user have said INCR, and stick with
252
+ # it.
253
+ if [ " $opt_send_type " = " incr" -a -z " $last_snap " ]; then
254
+ if [ -n " $opt_verbose " ]; then
255
+ echo " WARNING: No previous snapshots exist but we where called"
256
+ echo " with --send-incr. Can not continue."
257
+ echo " Please rerun with --send-full."
258
+ fi
259
+ return 1
260
+ fi
261
+
262
+ if [ -n " $opt_recursive " -a -n " $last_snap " ]; then
263
+ # STEP 3: Again, go through ALL snapshots that exists, but this
264
+ # time only look for the snapshots that 'starts with'
265
+ # the dataset/volume in question AND 'ends with'
266
+ # the exact snapshot name/date in step 2.
267
+ for jj in $SNAPSHOTS_OLD
268
+ do
269
+ if echo " $jj " | grep -qE " ^$dset .*@$last_snap " ; then
270
+ SNAPS_SEND=" $SNAPS_SEND
271
+ $jj "
272
+ fi
273
+ done
274
+ else
275
+ SNAPS_SEND=" $ii "
276
+ fi
277
+
278
+ # STEP 4: Go through all snapshots that is to be transfered and send them.
279
+ for jj in $SNAPS_SEND
280
+ do
281
+ if [ " $opt_send_type " = " incr" ]; then
282
+ do_run " zfs send $opt_send_opts -i $jj $ii | $remote "
283
+ else
284
+ do_run " zfs send $opt_send_opts -R $jj | $remote "
285
+ fi
286
+ done
287
+ done
288
+ }
206
289
207
290
# main ()
208
291
# {
@@ -212,6 +295,7 @@ GETOPT=$(getopt \
212
295
--longoptions=event:,keep:,label:,prefix:,sep: \
213
296
--longoptions=debug,help,quiet,syslog,verbose \
214
297
--longoptions=pre-snapshot:,post-snapshot:,destroy-only \
298
+ --longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
215
299
--options=dnshe:l:k:p:rs:qgv \
216
300
-- " $@ " ) \
217
301
|| exit 128
296
380
opt_recursive=' 1'
297
381
shift 1
298
382
;;
383
+ (--send-full)
384
+ opt_send_type=' full'
385
+
386
+ opt_send_host=$( echo " $2 " | sed ' s,:.*,,' )
387
+ opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
388
+
389
+ opt_send_opts=" $opt_send_opts -R"
390
+ shift 2
391
+ ;;
392
+ (--send-incr)
393
+ opt_send_type=' incr'
394
+
395
+ opt_send_host=$( echo " $2 " | sed ' s,:.*,,' )
396
+ opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
397
+ shift 2
398
+ ;;
399
+ (--send-opts)
400
+ opt_send_opts=" $2 "
401
+ shift 2
402
+ ;;
403
+ (--recv-opts)
404
+ opt_recv_opts=" $2 "
405
+ shift 2
406
+ ;;
299
407
(--sep)
300
408
case " $2 " in
301
409
([[:alnum:]_.:\ -])
@@ -567,6 +675,8 @@ test -n "$opt_dry_run" \
567
675
do_snapshots " $SNAPPROP " " " " $SNAPNAME " " $SNAPGLOB " " $TARGETS_REGULAR "
568
676
do_snapshots " $SNAPPROP " " -r" " $SNAPNAME " " $SNAPGLOB " " $TARGETS_RECURSIVE "
569
677
678
+ do_send " $SNAPNAME " " $SNAPGLOB "
679
+
570
680
print_log notice " @$SNAPNAME ," \
571
681
" $SNAPSHOT_COUNT created," \
572
682
" $DESTRUCTION_COUNT destroyed," \
0 commit comments