19 Commits

Author SHA1 Message Date
Jonathan Carter
9c6f065589 Check whether we have zfs-auto-snapshot before running it 2017-06-06 11:06:16 +02:00
Jonathan Carter
62f5f7d920 Merge pull request #33 from aphor/master
zfs destroy will use -d for deferred destruction
2017-01-27 20:28:01 +02:00
Jonathan Carter
b74769894c Merge pull request #35 from bernhardschmidt/master
Fix frequent cronjob
2017-01-27 20:08:24 +02:00
Jonathan Carter
11130ba8d6 Merge pull request #43 from FransUrbo/prettify_SNAPSHOTS_OLD
"Prettify" long command line
2017-01-27 20:07:39 +02:00
Turbo Fredriksson
c4ad5eeac5 Break up the huge line where SNAPSHOTS_OLD (if --fast was used) to make
it easier to read and follow.
2015-04-03 17:34:16 +02:00
Bernhard Schmidt
b2e97c5fe0 use long options in frequent cronjob 2014-12-29 20:07:18 +01:00
Bernhard Schmidt
d3bdd2dc23 include default installation prefix in frequent cronjob 2014-12-29 20:05:26 +01:00
Jeremy McMillan
f2767ad43a zfs destroy will use -d for deferred destruction
I am working on a complimentary script that does log-shipping style replication to a backup volume for highly efficient incremental backups. This relies on "zfs send -R" and that the sets of snapshots existing on the source and backup destination overlap by at least one snapshot. I plan to use snapshot clones to place a "checkpoint" reservation on a snapshot that will be required for future backups.

In order to keep zfs-auto-snapshot from destroying a snapshot necessary for a future incremental backup replication stream, I will create an unmounted clone of that snapshot, and destroy any prior clones when the backup completes. 

Any snapshots destroyed by the zfs-auto-snapshot "zfs destroy -d" will be destroyed as the dependent clones are destroyed. Without the -d option, zfs-auto-snapshot would fail to destroy the old snapshot with a checkpoint clone, and it would persist until later snapshot jobs destroy it in subsequent runs. Since monthlies and weeklies are relatively infrequent, deferred destruction will reap the snapshots opportunistically as soon as the "checkpoint" clones are gone. Intermediate snapshots between the "checkpoint" reserved snapshots and the recent snapshots preserved by the zfs-auto-snapshot.sh will still be immediately destroyed.
2014-11-17 19:21:52 -06:00
Darik Horn
d5cb31aaae Install the cron.d part without the execute bit.
Resolve this lintian error:

	E: zfs-auto-snapshot: bad-permissions-for-etc-cron.d-script etc/cron.d/zfs-auto-snapshot 0755 != 0644
	W: zfs-auto-snapshot: executable-not-elf-or-script etc/cron.d/zfs-auto-snapshot

This should also resolve a related failure on Arch Linux.

Closes: zfsonlinux/zfs-auto-snapshot#4
Thanks: @bitloggerig
Thanks: @scottj97
2014-10-13 23:12:53 -05:00
Darik Horn
1ce72681bf Merge pull request #31 from virtualguy/patch-1
Update README
2014-10-13 20:41:01 -04:00
Darik Horn
a0df1ebcc1 Merge pull request #30 from mbaynton/remove-only
--destroy-only switch, --{pre,post} fixes
2014-10-13 20:39:40 -04:00
Darik Horn
0be4466869 Merge pull request #29 from mmalecki/pre-post
Add pre and post snapshot hooks
2014-10-13 20:37:12 -04:00
Darik Horn
9d2398ed8e Merge pull request #26 from borutmrak/master
Fix manpage path
2014-10-13 20:31:06 -04:00
virtualguy
bc1b65a66e Update README
Add some simple installation instructions
2014-08-18 21:38:32 +12:00
Mike Baynton
bfe4c911a8 Make --{pre,post}-snapshot optional, add --destroy-only, revise docs 2014-08-09 17:23:02 -05:00
Maciej Małecki
10f9b3e336 Document `--{pre,post}-snapshot 2014-08-07 02:08:29 +02:00
Maciej Małecki
c08f366c1c Abort if pre snapshot hook returns non-zero 2014-08-07 02:08:29 +02:00
Maciej Małecki
da5a8bd5b7 Add --{pre,post}-snapshot for pre and post creation hook 2014-08-07 02:08:23 +02:00
Borut Mrak
a1b89b6fef Makefile:
* Remove PREFIX from cron scripts - they should always end up in /etc.
  * Leave PREFIX for man page and program, and set it to /usr/local by default.
2014-04-23 09:31:30 +02:00
9 changed files with 119 additions and 28 deletions

View File

@@ -1,16 +1,18 @@
PREFIX := /usr/local
all: all:
install: install:
install -d $(DESTDIR)$(PREFIX)/etc/cron.d install -d $(DESTDIR)/etc/cron.d
install -d $(DESTDIR)$(PREFIX)/etc/cron.daily install -d $(DESTDIR)/etc/cron.daily
install -d $(DESTDIR)$(PREFIX)/etc/cron.hourly install -d $(DESTDIR)/etc/cron.hourly
install -d $(DESTDIR)$(PREFIX)/etc/cron.weekly install -d $(DESTDIR)/etc/cron.weekly
install -d $(DESTDIR)$(PREFIX)/etc/cron.monthly install -d $(DESTDIR)/etc/cron.monthly
install etc/zfs-auto-snapshot.cron.frequent $(DESTDIR)$(PREFIX)/etc/cron.d/zfs-auto-snapshot install -m 0644 etc/zfs-auto-snapshot.cron.frequent $(DESTDIR)/etc/cron.d/zfs-auto-snapshot
install etc/zfs-auto-snapshot.cron.hourly $(DESTDIR)$(PREFIX)/etc/cron.hourly/zfs-auto-snapshot install etc/zfs-auto-snapshot.cron.hourly $(DESTDIR)/etc/cron.hourly/zfs-auto-snapshot
install etc/zfs-auto-snapshot.cron.daily $(DESTDIR)$(PREFIX)/etc/cron.daily/zfs-auto-snapshot install etc/zfs-auto-snapshot.cron.daily $(DESTDIR)/etc/cron.daily/zfs-auto-snapshot
install etc/zfs-auto-snapshot.cron.weekly $(DESTDIR)$(PREFIX)/etc/cron.weekly/zfs-auto-snapshot install etc/zfs-auto-snapshot.cron.weekly $(DESTDIR)/etc/cron.weekly/zfs-auto-snapshot
install etc/zfs-auto-snapshot.cron.monthly $(DESTDIR)$(PREFIX)/etc/cron.monthly/zfs-auto-snapshot install etc/zfs-auto-snapshot.cron.monthly $(DESTDIR)/etc/cron.monthly/zfs-auto-snapshot
install -d $(DESTDIR)$(PREFIX)/share/man/man8 install -d $(DESTDIR)$(PREFIX)/share/man/man8
install src/zfs-auto-snapshot.8 $(DESTDIR)$(PREFIX)/share/man/man8/zfs-auto-snapshot.8 install src/zfs-auto-snapshot.8 $(DESTDIR)$(PREFIX)/share/man/man8/zfs-auto-snapshot.8
install -d $(DESTDIR)$(PREFIX)/sbin install -d $(DESTDIR)$(PREFIX)/sbin

9
README
View File

@@ -10,3 +10,12 @@ snapshots if it is installed.
This program is a posixly correct bourne shell script. It depends only on This program is a posixly correct bourne shell script. It depends only on
the zfs utilities and cron, and can run in the dash shell. the zfs utilities and cron, and can run in the dash shell.
Installation:
-------------
wget https://github.com/zfsonlinux/zfs-auto-snapshot/archive/master.zip
unzip master.zip
cd zfs-auto-snapshot-master
make install

View File

@@ -1,2 +1,5 @@
#!/bin/sh #!/bin/sh
exec zfs-auto-snapshot --quiet --syslog --label=daily --keep=31 //
# Only call zfs-auto-snapshot if it's available
exec which zfs-auto-snapshot > /dev/null && \
zfs-auto-snapshot --quiet --syslog --label=daily --keep=31 //

View File

@@ -1,3 +1,3 @@
PATH="/usr/bin:/bin:/usr/sbin:/sbin" PATH="/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
*/15 * * * * root zfs-auto-snapshot -q -g --label=frequent --keep=4 // */15 * * * * root which zfs-auto-snapshot > /dev/null && zfs-auto-snapshot --quiet --syslog --label=frequent --keep=4 //

View File

@@ -1,2 +1,5 @@
#!/bin/sh #!/bin/sh
exec zfs-auto-snapshot --quiet --syslog --label=hourly --keep=24 //
# Only call zfs-auto-snapshot if it's available
exec which zfs-auto-snapshot > /dev/null && \
zfs-auto-snapshot --quiet --syslog --label=hourly --keep=24 //

View File

@@ -1,2 +1,5 @@
#!/bin/sh #!/bin/sh
exec zfs-auto-snapshot --quiet --syslog --label=monthly --keep=12 //
# Only call zfs-auto-snapshot if it's available
exec which zfs-auto-snapshot > /dev/null && \
zfs-auto-snapshot --quiet --syslog --label=monthly --keep=12 //

View File

@@ -1,2 +1,5 @@
#!/bin/sh #!/bin/sh
exec zfs-auto-snapshot --quiet --syslog --label=weekly --keep=8 //
# Only call zfs-auto-snapshot if it's available
exec which zfs-auto-snapshot > /dev/null && \
zfs-auto-snapshot --quiet --syslog --label=weekly --keep=8 //

View File

@@ -64,6 +64,27 @@ Snapshot named filesystem and all descendants.
\fB\-v\fR, \fB\-\-verbose\fR \fB\-v\fR, \fB\-\-verbose\fR
Print info messages. Print info messages.
.TP .TP
\fB\-\-pre-snapshot\fR=\fICOMMAND\fR
Command to run before each dataset is snapshotted.
It is passed the dataset and snapshot name. If it
returns non-zero, snapshotting this dataset is
aborted.
.TP
\fB\-\-post-snapshot\fR=\fICOMMAND\fR
Command to run after each dataset is snapshotted.
It is passed the dataset and snapshot name.
.TP
\fB\-\-destroy-only\fR
Do not create new snapshots, but do destroy older
snapshots. Has no effect unless used with \fB\-k\fR.
.IP
A non-obvious use may be constructon of cron jobs or
scripts that run pre-snapshot command(s), then run
zfs-auto-snapshot (without \fB\-k\fR) to quickly
snapshot all datasets, then run post-snapshot
command(s) and clean up with zfs-auto-snapshot
\fB\-\-destroy-only\fR.
.TP
name name
Filesystem and volume names, or '//' for all ZFS datasets. Filesystem and volume names, or '//' for all ZFS datasets.
.SH SEE ALSO .SH SEE ALSO

View File

@@ -39,6 +39,9 @@ opt_setauto=''
opt_syslog='' opt_syslog=''
opt_skip_scrub='' opt_skip_scrub=''
opt_verbose='' opt_verbose=''
opt_pre_snapshot=''
opt_post_snapshot=''
opt_do_snapshots=1
# Global summary statistics. # Global summary statistics.
DESTRUCTION_COUNT='0' DESTRUCTION_COUNT='0'
@@ -69,6 +72,7 @@ print_usage ()
-g, --syslog Write messages into the system log. -g, --syslog Write messages into the system log.
-r, --recursive Snapshot named filesystem and all descendants. -r, --recursive Snapshot named filesystem and all descendants.
-v, --verbose Print info messages. -v, --verbose Print info messages.
--destroy-only Only destroy older snapshots, do not create new ones.
name Filesystem and volume names, or '//' for all ZFS datasets. name Filesystem and volume names, or '//' for all ZFS datasets.
" "
} }
@@ -148,6 +152,7 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
local GLOB="$4" local GLOB="$4"
local TARGETS="$5" local TARGETS="$5"
local KEEP='' local KEEP=''
local RUNSNAP=1
# global DESTRUCTION_COUNT # global DESTRUCTION_COUNT
# global SNAPSHOT_COUNT # global SNAPSHOT_COUNT
@@ -156,12 +161,20 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
for ii in $TARGETS for ii in $TARGETS
do do
if do_run "zfs snapshot $PROPS $FLAGS '$ii@$NAME'" if [ -n "$opt_do_snapshots" ]
then then
SNAPSHOT_COUNT=$(( $SNAPSHOT_COUNT + 1 )) if [ "$opt_pre_snapshot" != "" ]
else then
WARNING_COUNT=$(( $WARNING_COUNT + 1 )) do_run "$opt_pre_snapshot $ii $NAME" || RUNSNAP=0
continue fi
if [ $RUNSNAP -eq 1 ] && do_run "zfs snapshot $PROPS $FLAGS '$ii@$NAME'"
then
[ "$opt_post_snapshot" != "" ] && do_run "$opt_post_snapshot $ii $NAME"
SNAPSHOT_COUNT=$(( $SNAPSHOT_COUNT + 1 ))
else
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
continue
fi
fi fi
# Retain at most $opt_keep number of old snapshots of this filesystem, # Retain at most $opt_keep number of old snapshots of this filesystem,
@@ -178,7 +191,7 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
KEEP=$(( $KEEP - 1 )) KEEP=$(( $KEEP - 1 ))
if [ "$KEEP" -le '0' ] if [ "$KEEP" -le '0' ]
then then
if do_run "zfs destroy $FLAGS '$jj'" if do_run "zfs destroy -d $FLAGS '$jj'"
then then
DESTRUCTION_COUNT=$(( $DESTRUCTION_COUNT + 1 )) DESTRUCTION_COUNT=$(( $DESTRUCTION_COUNT + 1 ))
else else
@@ -198,6 +211,7 @@ GETOPT=$(getopt \
--longoptions=default-exclude,dry-run,fast,skip-scrub,recursive \ --longoptions=default-exclude,dry-run,fast,skip-scrub,recursive \
--longoptions=event:,keep:,label:,prefix:,sep: \ --longoptions=event:,keep:,label:,prefix:,sep: \
--longoptions=debug,help,quiet,syslog,verbose \ --longoptions=debug,help,quiet,syslog,verbose \
--longoptions=pre-snapshot:,post-snapshot:,destroy-only \
--options=dnshe:l:k:p:rs:qgv \ --options=dnshe:l:k:p:rs:qgv \
-- "$@" ) \ -- "$@" ) \
|| exit 128 || exit 128
@@ -308,6 +322,18 @@ do
opt_verbose='1' opt_verbose='1'
shift 1 shift 1
;; ;;
(--pre-snapshot)
opt_pre_snapshot="$2"
shift 2
;;
(--post-snapshot)
opt_post_snapshot="$2"
shift 2
;;
(--destroy-only)
opt_do_snapshots=''
shift 1
;;
(--) (--)
shift 1 shift 1
break break
@@ -347,7 +373,11 @@ ZFS_LIST=$(env LC_ALL=C zfs list -H -t filesystem,volume -s name \
if [ -n "$opt_fast_zfs_list" ] if [ -n "$opt_fast_zfs_list" ]
then then
SNAPSHOTS_OLD=$(env LC_ALL=C zfs list -H -t snapshot -o name -s name|grep $opt_prefix |awk '{ print substr( $0, length($0) - 14, length($0) ) " " $0}' |sort -r -k1,1 -k2,2|awk '{ print substr( $0, 17, length($0) )}') \ SNAPSHOTS_OLD=$(env LC_ALL=C zfs list -H -t snapshot -o name -s name | \
grep $opt_prefix | \
awk '{ print substr( $0, length($0) - 14, length($0) ) " " $0}' | \
sort -r -k1,1 -k2,2 | \
awk '{ print substr( $0, 17, length($0) )}') \
|| { print_log error "zfs list $?: $SNAPSHOTS_OLD"; exit 137; } || { print_log error "zfs list $?: $SNAPSHOTS_OLD"; exit 137; }
else else
SNAPSHOTS_OLD=$(env LC_ALL=C zfs list -H -t snapshot -S creation -o name) \ SNAPSHOTS_OLD=$(env LC_ALL=C zfs list -H -t snapshot -S creation -o name) \
@@ -512,11 +542,28 @@ SNAPNAME="$opt_prefix${opt_label:+$opt_sep$opt_label}-$DATE"
# The expression for matching old snapshots. -YYYY-MM-DD-HHMM # The expression for matching old snapshots. -YYYY-MM-DD-HHMM
SNAPGLOB="$opt_prefix${opt_label:+?$opt_label}????????????????" SNAPGLOB="$opt_prefix${opt_label:+?$opt_label}????????????????"
test -n "$TARGETS_REGULAR" \ if [ -n "$opt_do_snapshots" ]
&& print_log info "Doing regular snapshots of $TARGETS_REGULAR" then
test -n "$TARGETS_REGULAR" \
&& print_log info "Doing regular snapshots of $TARGETS_REGULAR"
test -n "$TARGETS_RECURSIVE" \ test -n "$TARGETS_RECURSIVE" \
&& print_log info "Doing recursive snapshots of $TARGETS_RECURSIVE" && print_log info "Doing recursive snapshots of $TARGETS_RECURSIVE"
if test -n "$opt_keep" && [ "$opt_keep" -ge "1" ]
then
print_log info "Destroying all but the newest $opt_keep snapshots of each dataset."
fi
elif test -n "$opt_keep" && [ "$opt_keep" -ge "1" ]
then
test -n "$TARGETS_REGULAR" \
&& print_log info "Destroying all but the newest $opt_keep snapshots of $TARGETS_REGULAR"
test -n "$TARGETS_RECURSIVE" \
&& print_log info "Recursively destroying all but the newest $opt_keep snapshots of $TARGETS_RECURSIVE"
else
print_log notice "Only destroying snapshots, but count of snapshots to preserve not given. Nothing to do."
fi
test -n "$opt_dry_run" \ test -n "$opt_dry_run" \
&& print_log info "Doing a dry run. Not running these commands..." && print_log info "Doing a dry run. Not running these commands..."