@@ -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,79 @@ 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 remote=" ssh $opt_send_host zfs receive $opt_recv_opts $opt_recv_pool "
222+ local ii
223+ local jj
224+
225+ # STEP 1: Go throug all snapshots we've created
226+ for ii in $SNAPS_DONE
227+ do
228+ opts=' '
229+ SNAPS_SEND=' '
230+
231+ dset=${ii%@* }
232+
233+ # STEP 2: Go through ALL snapshots that exist, look for exact
234+ # match on dataset/volume (with snapshot matching 'GLOB').
235+ for jj in $SNAPSHOTS_OLD
236+ do
237+ # Check whether this is an old snapshot of the filesystem.
238+ if [ -z " ${jj# $dset @ $GLOB } " ]; then
239+ # We want the FIRST one (which is the last in time
240+ # before the one we just created in do_snapshot()).
241+ # Also, here we just need the snapshot name.
242+ last_snap=" ${jj#*@ } "
243+ break
244+ fi
245+ done
246+
247+ # NOTE: If we don't have any previous snapshots (for example, we've
248+ # just created the first one) we can end up with last_snap=''
249+ # here.
250+ # If we're called with '--send-incr' we have to options:
251+ # 1: We change from incremental to full.
252+ # 2: We accept that the user have said INCR, and stick with
253+ # it.
254+ if [ " $opt_send_type " = " incr" -a -z " $last_snap " ]; then
255+ if [ -n " $opt_verbose " ]; then
256+ echo " WARNING: No previous snapshots exist but we where called"
257+ echo " with --send-incr. Can not continue."
258+ echo " Please rerun with --send-full."
259+ fi
260+ return 1
261+ fi
262+
263+ if [ -n " $opt_recursive " -a -n " $last_snap " ]; then
264+ # STEP 3: Again, go through ALL snapshots that exists, but this
265+ # time only look for the snapshots that 'starts with'
266+ # the dataset/volume in question AND 'ends with'
267+ # the exact snapshot name/date in step 2.
268+ for jj in $SNAPSHOTS_OLD
269+ do
270+ if echo " $jj " | grep -qE " ^$dset .*@$last_snap " ; then
271+ SNAPS_SEND=" $SNAPS_SEND
272+ $jj "
273+ fi
274+ done
275+ else
276+ SNAPS_SEND=" $ii "
277+ fi
278+
279+ # STEP 4: Go through all snapshots that is to be transfered and send them.
280+ for jj in $SNAPS_SEND
281+ do
282+ if [ " $opt_send_type " = " incr" ]; then
283+ do_run " zfs send $opt_send_opts -i $jj $ii | $remote "
284+ else
285+ do_run " zfs send $opt_send_opts -R $jj | $remote "
286+ fi
287+ done
288+ done
289+ }
206290
207291# main ()
208292# {
@@ -212,6 +296,7 @@ GETOPT=$(getopt \
212296 --longoptions=event:,keep:,label:,prefix:,sep: \
213297 --longoptions=debug,help,quiet,syslog,verbose \
214298 --longoptions=pre-snapshot:,post-snapshot:,destroy-only \
299+ --longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
215300 --options=dnshe:l:k:p:rs:qgv \
216301 -- " $@ " ) \
217302 || exit 128
296381 opt_recursive=' 1'
297382 shift 1
298383 ;;
384+ (--send-full)
385+ opt_send_type=' full'
386+
387+ opt_send_host=$( echo " $2 " | sed ' s,:.*,,' )
388+ opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
389+
390+ opt_send_opts=" $opt_send_opts -R"
391+ shift 2
392+ ;;
393+ (--send-incr)
394+ opt_send_type=' incr'
395+
396+ opt_send_host=$( echo " $2 " | sed ' s,:.*,,' )
397+ opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
398+ shift 2
399+ ;;
400+ (--send-opts)
401+ opt_send_opts=" $2 "
402+ shift 2
403+ ;;
404+ (--recv-opts)
405+ opt_recv_opts=" $2 "
406+ shift 2
407+ ;;
299408 (--sep)
300409 case " $2 " in
301410 ([[:alnum:]_.:\ -])
@@ -567,6 +676,8 @@ test -n "$opt_dry_run" \
567676do_snapshots " $SNAPPROP " " " " $SNAPNAME " " $SNAPGLOB " " $TARGETS_REGULAR "
568677do_snapshots " $SNAPPROP " " -r" " $SNAPNAME " " $SNAPGLOB " " $TARGETS_RECURSIVE "
569678
679+ do_send " $SNAPNAME " " $SNAPGLOB "
680+
570681print_log notice " @$SNAPNAME ," \
571682 " $SNAPSHOT_COUNT created," \
572683 " $DESTRUCTION_COUNT destroyed," \
0 commit comments