@@ -34,6 +34,11 @@ opt_keep=''
3434opt_label=' '
3535opt_prefix=' zfs-auto-snap'
3636opt_recursive=' '
37+ opt_send_type=' '
38+ opt_send_host=' '
39+ opt_recv_pool=' '
40+ opt_send_opts=' '
41+ opt_recv_opts=' '
3742opt_sep=' _'
3843opt_setauto=' '
3944opt_syslog=' '
@@ -68,6 +73,8 @@ print_usage ()
6873 -q, --quiet Suppress warnings and notices at the console.
6974 --send-full=F Send zfs full backup. Unimplemented.
7075 --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'.
7178 --sep=CHAR Use CHAR to separate date stamps in snapshot names.
7279 -g, --syslog Write messages into the system log.
7380 -r, --recursive Snapshot named filesystem and all descendants.
@@ -159,6 +166,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
159166 # global WARNING_COUNT
160167 # global SNAPSHOTS_OLD
161168
169+ SNAPS_DONE=' '
170+
162171 for ii in $TARGETS
163172 do
164173 if [ -n " $opt_do_snapshots " ]
@@ -170,6 +179,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
170179 if [ $RUNSNAP -eq 1 ] && do_run " zfs snapshot $PROPS $FLAGS '$ii @$NAME '"
171180 then
172181 [ " $opt_post_snapshot " != " " ] && do_run " $opt_post_snapshot $ii $NAME "
182+ [ -n " $opt_send_host " ] && SNAPS_DONE=" $SNAPS_DONE
183+ $ii @$NAME "
173184 SNAPSHOT_COUNT=$(( $SNAPSHOT_COUNT + 1 ))
174185 else
175186 WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
@@ -203,6 +214,78 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
203214 done
204215}
205216
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+ echo " zfs send $opt_send_opts -i $jj $ii | $remote "
283+ else
284+ echo " zfs send $opt_send_opts -R $jj | $remote "
285+ fi
286+ done
287+ done
288+ }
206289
207290# main ()
208291# {
@@ -212,6 +295,7 @@ GETOPT=$(getopt \
212295 --longoptions=event:,keep:,label:,prefix:,sep: \
213296 --longoptions=debug,help,quiet,syslog,verbose \
214297 --longoptions=pre-snapshot:,post-snapshot:,destroy-only \
298+ --longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
215299 --options=dnshe:l:k:p:rs:qgv \
216300 -- " $@ " ) \
217301 || exit 128
296380 opt_recursive=' 1'
297381 shift 1
298382 ;;
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+ ;;
299407 (--sep)
300408 case " $2 " in
301409 ([[:alnum:]_.:\ -])
@@ -567,6 +675,8 @@ test -n "$opt_dry_run" \
567675do_snapshots " $SNAPPROP " " " " $SNAPNAME " " $SNAPGLOB " " $TARGETS_REGULAR "
568676do_snapshots " $SNAPPROP " " -r" " $SNAPNAME " " $SNAPGLOB " " $TARGETS_RECURSIVE "
569677
678+ do_send " $SNAPNAME " " $SNAPGLOB "
679+
570680print_log notice " @$SNAPNAME ," \
571681 " $SNAPSHOT_COUNT created," \
572682 " $DESTRUCTION_COUNT destroyed," \
0 commit comments