forked from extern/zfs-auto-snapshot
Zevo support.
This commit is contained in:
parent
cc9f1802ed
commit
4d20aa4c79
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/opt/local/bin/bash
|
||||
|
||||
# zfs-auto-snapshot for Linux
|
||||
# Automatically create, rotate, and destroy periodic ZFS snapshots.
|
||||
@ -30,7 +30,7 @@ opt_default_exclude=''
|
||||
opt_dry_run=''
|
||||
opt_event='-'
|
||||
opt_keep=''
|
||||
opt_label=''
|
||||
opt_label='regular'
|
||||
opt_prefix='zfs-auto-snap'
|
||||
opt_recursive=''
|
||||
opt_sep='_'
|
||||
@ -38,40 +38,78 @@ opt_setauto=''
|
||||
opt_syslog=''
|
||||
opt_skip_scrub=''
|
||||
opt_verbose=''
|
||||
opt_remove=''
|
||||
opt_fallback='0'
|
||||
opt_force=''
|
||||
opt_sendprefix=''
|
||||
opt_send='no'
|
||||
opt_atonce='-I'
|
||||
opt_create='0'
|
||||
opt_destroy='0'
|
||||
|
||||
# if pipe needs to be used, uncomment opt_pipe="|"
|
||||
opt_sendtocmd='ssh -1 root@media -i /var/root/.ssh/media.rsa1'
|
||||
opt_pipe='|'
|
||||
|
||||
# Global summary statistics.
|
||||
DESTRUCTION_COUNT='0'
|
||||
SNAPSHOT_COUNT='0'
|
||||
WARNING_COUNT='0'
|
||||
CREATION_COUNT='0'
|
||||
KEEP=''
|
||||
|
||||
# Other global variables.
|
||||
SNAPSHOTS_OLD=''
|
||||
declare -a SNAPSHOTS_OLD_LOC
|
||||
declare -a SNAPSHOTS_OLD_REM
|
||||
declare -a CREATED_TARGETS
|
||||
declare -a ZFS_REMOTE_LIST
|
||||
declare -a ZFS_LOCAL_LIST
|
||||
declare -a TARGETS_DRECURSIVE
|
||||
declare -a TARGETS_DREGULAR
|
||||
declare -i RC
|
||||
|
||||
tmp_file_prefix='zfs-auto-snapshot'
|
||||
|
||||
|
||||
set -o pipefail
|
||||
|
||||
print_usage ()
|
||||
{
|
||||
echo "Usage: $0 [options] [-l label] <'//' | name [name...]>
|
||||
--default-exclude Exclude datasets if com.sun:auto-snapshot is unset.
|
||||
--remove-local=n Remove local snapshots after successfully sent via --send-incr or --send-full but still keeps n snapshots.
|
||||
-d, --debug Print debugging messages.
|
||||
-e, --event=EVENT Set the com.sun:auto-snapshot-desc property to EVENT.
|
||||
-n, --dry-run Print actions without actually doing anything.
|
||||
-s, --skip-scrub Do not snapshot filesystems in scrubbing pools.
|
||||
-h, --help Print this usage message.
|
||||
-k, --keep=NUM Keep NUM recent snapshots and destroy older snapshots.
|
||||
-l, --label=LAB LAB is usually 'hourly', 'daily', or 'monthly'.
|
||||
-l, --label=LAB LAB is usually 'hourly', 'daily', or 'monthly' (default is 'regular').
|
||||
-p, --prefix=PRE PRE is 'zfs-auto-snap' by default.
|
||||
-q, --quiet Suppress warnings and notices at the console.
|
||||
-c, --create Create missing filesystems at destination.
|
||||
-i, --send-at-once Send more incremental snapshots at once in one package (-i argument is passed to zfs send instead of -I).
|
||||
--send-full=F Send zfs full backup. Unimplemented.
|
||||
--send-incr=F Send zfs incremental backup. Unimplemented.
|
||||
--sep=CHAR Use CHAR to separate date stamps in snapshot names.
|
||||
-b, --rollback Roll back remote filesystem to match currently sending snapshot.
|
||||
-X, --destroy Destroy remote snapshots to allow --send-full if destination has snapshots (needed for -F in case incremental
|
||||
snapshots on local and remote do not match).
|
||||
-F, --fallback Allow fallback from --send-incr to --send-full, if incremental sending is not possible (filesystem on remote just
|
||||
created or snapshots do not match - see -X).
|
||||
-g, --syslog Write messages into the system log.
|
||||
-r, --recursive Snapshot named filesystem and all descendants.
|
||||
-R, --replication Use zfs's replication (zfs send -R) instead of simple send over newly created snapshots (check man zfs for details).
|
||||
-v, --verbose Print info messages.
|
||||
-f, --force Passes -F argument to zfs receive
|
||||
name Filesystem and volume names, or '//' for all ZFS datasets.
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
trap "{ rm -f $LOCKFILE; }" EXIT
|
||||
|
||||
|
||||
print_log () # level, message, ...
|
||||
{
|
||||
LEVEL=$1
|
||||
@ -120,13 +158,15 @@ print_log () # level, message, ...
|
||||
|
||||
do_run () # [argv]
|
||||
{
|
||||
|
||||
if [ -n "$opt_dry_run" ]
|
||||
then
|
||||
echo $*
|
||||
print_log notice "... running: $*"
|
||||
RC="$?"
|
||||
else
|
||||
eval $*
|
||||
RC="$?"
|
||||
|
||||
if [ "$RC" -eq '0' ]
|
||||
then
|
||||
print_log debug "$*"
|
||||
@ -134,26 +174,90 @@ do_run () # [argv]
|
||||
print_log warning "$* returned $RC"
|
||||
fi
|
||||
fi
|
||||
|
||||
return "$RC"
|
||||
}
|
||||
|
||||
|
||||
do_send ()
|
||||
{
|
||||
local SENDTYPE="$1"
|
||||
local SNAPFROM="$2"
|
||||
local SNAPTO="$3"
|
||||
local SENDFLAGS="$4"
|
||||
local REMOTEFS="$5"
|
||||
|
||||
|
||||
test $SENDTYPE = "incr" && do_run "zfs send " "$SENDFLAGS" "$opt_atonce $SNAPFROM $SNAPTO" "$opt_pipe" "$opt_sendtocmd" "zfs recv $opt_force -u $REMOTEFS"
|
||||
test $SENDTYPE = "full" && do_run "zfs send " "$SENDFLAGS" "$SNAPTO" "$opt_pipe" "$opt_sendtocmd" "zfs recv $opt_force -u $REMOTEFS"
|
||||
|
||||
test "$RC" -ne '0' && WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
|
||||
|
||||
return "$RC"
|
||||
|
||||
}
|
||||
|
||||
do_delete ()
|
||||
{
|
||||
|
||||
local DEL_TYPE="$1"
|
||||
local SNAPNAME="$2"
|
||||
local FLAGS="$3"
|
||||
|
||||
KEEP=$(( $KEEP - 1 ))
|
||||
if [ "$KEEP" -le '0' ]
|
||||
then
|
||||
case "$DEL_TYPE" in
|
||||
(remote)
|
||||
do_run "$opt_sendtocmd" "zfs destroy $FLAGS '$SNAPNAME'"
|
||||
;;
|
||||
(local)
|
||||
do_run "zfs destroy $FLAGS '$SNAPNAME'"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$RC" -eq 0 ]
|
||||
then
|
||||
DESTRUCTION_COUNT=$(( $DESTRUCTION_COUNT + 1 ))
|
||||
else
|
||||
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
is_member ()
|
||||
{
|
||||
local ARRAY=(${1})
|
||||
local MEMBER="$2"
|
||||
declare -i ISMEMBER=0
|
||||
|
||||
result=$(printf "%s\n" "${ARRAY[@]}"| grep -m1 -x "$MEMBER")
|
||||
if [ -n "$result" -a -z "${result#$MEMBER}" ]; then ISMEMBER=1; fi
|
||||
|
||||
return "$ISMEMBER"
|
||||
}
|
||||
|
||||
do_snapshots () # properties, flags, snapname, oldglob, [targets...]
|
||||
{
|
||||
local PROPS="$1"
|
||||
local FLAGS="$2"
|
||||
local sFLAGS="$2"
|
||||
local NAME="$3"
|
||||
local GLOB="$4"
|
||||
local TARGETS="$5"
|
||||
local TARGETS=(${5})
|
||||
local KEEP=''
|
||||
|
||||
test "$sFLAGS" = '-R' && FLAGS='-r'
|
||||
|
||||
# global DESTRUCTION_COUNT
|
||||
# global SNAPSHOT_COUNT
|
||||
# global WARNING_COUNT
|
||||
# global SNAPSHOTS_OLD
|
||||
|
||||
for ii in $TARGETS
|
||||
for ii in ${TARGETS[@]}
|
||||
do
|
||||
|
||||
FALLBACK='0'
|
||||
SND_RC='1'
|
||||
|
||||
print_log debug "...Snapshooting $ii"
|
||||
|
||||
if do_run "zfs snapshot $PROPS $FLAGS '$ii@$NAME'"
|
||||
then
|
||||
SNAPSHOT_COUNT=$(( $SNAPSHOT_COUNT + 1 ))
|
||||
@ -161,42 +265,148 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...]
|
||||
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
if [ "$opt_send" = "incr" ]
|
||||
then
|
||||
LAST_REMOTE=$(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep "$opt_sendprefix$ii@" | grep -m1 . | awk -F'@' '{print $2}')
|
||||
|
||||
if [ -z "$LAST_REMOTE" ]
|
||||
then
|
||||
# no snapshot on remote
|
||||
FALLBACK='1'
|
||||
else
|
||||
# last snapshot on remote is no more available on local, this applies both for -r and non -r runs
|
||||
if [ $(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep -e ^$opt_sendprefix$ii.*@$LAST_REMOTE | grep -c . ) -ne \
|
||||
$(printf "%s\n" "${SNAPSHOTS_OLD_LOC[@]}" | grep -e ^$ii.*@$LAST_REMOTE | grep -c . ) ]
|
||||
then
|
||||
FALLBACK='3'
|
||||
fi
|
||||
fi
|
||||
|
||||
# remote filesystem just created. if -R run, check childen as well
|
||||
is_member "${CREATED_TARGETS[*]}" "$opt_sendprefix$ii"
|
||||
if [ "$?" -eq 1 ]; then
|
||||
FALLBACK='2';
|
||||
elif [ -n "$sFLAGS" ]; then
|
||||
if [ test $(printf "%s\n" ${CREATED_TARGETS[@]} | grep ^"$opt_sendprefix$ii/" ) != '' ]; then FALLBACK='4'; fi
|
||||
fi
|
||||
|
||||
case "$FALLBACK" in
|
||||
(1)
|
||||
print_log info "falling back to full send, no snapshot exists at destination: $ii"
|
||||
;;
|
||||
(2|4)
|
||||
print_log info "falling back to full send, remote filesystem was just created: $ii"
|
||||
;;
|
||||
(3)
|
||||
print_log info "falling back to full send, last snapshot on remote is not available on local: $ii"
|
||||
;;
|
||||
(0)
|
||||
do_send "incr" "$ii@$LAST_REMOTE" "$ii@$NAME" "$sFLAGS" "$opt_sendprefix$ii"
|
||||
SND_RC="$?"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$FALLBACK" in
|
||||
(3|4)
|
||||
test "$opt_destroy" -eq '1' && do_run "$opt_sendtocmd" "zfs list -H -t snapshot -o name" "|" "grep $opt_sendprefix$ii@" "$opt_pipe" "$opt_sendtocmd" "xargs -L1 zfs destroy $FLAGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
||||
if [ "$opt_send" = "full" -o "$FALLBACK" -ne '0' -a "$opt_fallback" -eq '1' ]
|
||||
then
|
||||
do_send "full" "" "$ii@$NAME" "$sFLAGS" "$opt_sendprefix$ii"
|
||||
SND_RC="$?"
|
||||
fi
|
||||
|
||||
|
||||
# Retain at most $opt_keep number of old snapshots of this filesystem,
|
||||
# including the one that was just recently created.
|
||||
test -z "$opt_keep" && continue
|
||||
KEEP="$opt_keep"
|
||||
|
||||
if [ -z "$opt_keep" ]
|
||||
then
|
||||
print_log debu "Number of snapshots not specified. Keeping all."
|
||||
continue
|
||||
elif [ "$opt_send" != "no" ] && [ "$SND_RC" -ne '0' ]
|
||||
then
|
||||
print_log debug "Sending of filesystem was requested, but send failed. Ommiting destroy procedures."
|
||||
continue
|
||||
elif [ "$opt_send" != "no" -a -n "$opt_remove" ]
|
||||
then
|
||||
KEEP="$opt_remove"
|
||||
print_log debug "Sending was successful, removal of local snapshots requested. Keeping only $KEEP."
|
||||
else
|
||||
KEEP="$opt_keep"
|
||||
print_log debug "Deleting local snapshots, keeping $KEEP."
|
||||
fi
|
||||
|
||||
# ASSERT: The old snapshot list is sorted by increasing age.
|
||||
for jj in $SNAPSHOTS_OLD
|
||||
for jj in ${SNAPSHOTS_OLD_LOC[@]}
|
||||
do
|
||||
# Check whether this is an old snapshot of the filesystem.
|
||||
if [ -z "${jj#$ii@$GLOB}" ]
|
||||
then
|
||||
KEEP=$(( $KEEP - 1 ))
|
||||
if [ "$KEEP" -le '0' ]
|
||||
then
|
||||
if do_run "zfs destroy $FLAGS '$jj'"
|
||||
then
|
||||
DESTRUCTION_COUNT=$(( $DESTRUCTION_COUNT + 1 ))
|
||||
else
|
||||
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
test -z "${jj#$ii@$GLOB}" -o -z "${jj##$ii@$opt_prefix*}" -a -n "$opt_remove" \
|
||||
-a "$opt_send" != "no" && do_delete "local" "$jj" "$FLAGS"
|
||||
done
|
||||
|
||||
if [ "$opt_send" = "no" -o "$sFLAGS" = "-R" ]
|
||||
then
|
||||
print_log debug "No sending option or replication, skipping remote snapshot removal."
|
||||
continue
|
||||
elif [ "$opt_destroy" -eq '1' -a "$FALLBACK" -eq '3' ]
|
||||
then
|
||||
print_log debug "Sent full copy, all remote snapshots were already destroyed."
|
||||
continue
|
||||
else
|
||||
KEEP="$opt_keep"
|
||||
print_log debug "Deleting remote snapshots, keeping only $KEEP."
|
||||
fi
|
||||
|
||||
# ASSERT: The old snapshot list is sorted by increasing age.
|
||||
for jj in ${SNAPSHOTS_OLD_REM[@]}
|
||||
do
|
||||
# Check whether this is an old snapshot of the filesystem.
|
||||
test -z "${jj#$opt_sendprefix$ii@$GLOB}" && do_delete "remote" "$jj" "$FLAGS"
|
||||
done
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
do_createfs ()
|
||||
{
|
||||
|
||||
local FS=(${1})
|
||||
|
||||
for ii in ${FS[@]}; do
|
||||
|
||||
print_log debug "checking: $opt_sendprefix$ii"
|
||||
|
||||
if is_member "${ZFS_REMOTE_LIST[*]}" "$opt_sendprefix$ii" -eq 0
|
||||
then
|
||||
print_log debug "creating: $opt_sendprefix$ii"
|
||||
|
||||
if do_run "$opt_sendtocmd" "zfs create $opt_sendprefix$ii"
|
||||
then
|
||||
CREATION_COUNT=$(( $CREATION_COUNT + 1 ))
|
||||
CREATED_TARGETS=( ${CREATED_TARGETS[@]} "$opt_sendprefix$ii" )
|
||||
else
|
||||
WARNING_COUNT=$(( $WARNING_COUNT + 1 ))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
# main ()
|
||||
# {
|
||||
|
||||
GETOPT=$(getopt \
|
||||
--longoptions=default-exclude,dry-run,skip-scrub,recursive \
|
||||
--longoptions=event:,keep:,label:,prefix:,sep: \
|
||||
--longoptions=debug,help,quiet,syslog,verbose \
|
||||
--options=dnshe:l:k:p:rs:qgv \
|
||||
|
||||
GETOPT=$('/opt/local/bin/getopt' \
|
||||
--longoptions=default-exclude,dry-run,skip-scrub,recursive,send-atonce \
|
||||
--longoptions=event:,keep:,label:,prefix:,sep:,create,fallback,rollback \
|
||||
--longoptions=debug,help,quiet,syslog,verbose,send-full:,send-incr:,remove-local:,destroy \
|
||||
--options=dnshe:l:k:p:rs:qgvfixcXFbR \
|
||||
-- "$@" ) \
|
||||
|| exit 128
|
||||
|
||||
@ -211,7 +421,11 @@ do
|
||||
opt_verbose='1'
|
||||
shift 1
|
||||
;;
|
||||
(--default-exclude)
|
||||
(-c|--create)
|
||||
opt_create='1'
|
||||
shift 1
|
||||
;;
|
||||
(-x|--default-exclude)
|
||||
opt_default_exclude='1'
|
||||
shift 1
|
||||
;;
|
||||
@ -273,7 +487,24 @@ do
|
||||
shift 1
|
||||
;;
|
||||
(-r|--recursive)
|
||||
opt_recursive='1'
|
||||
opt_recursive=' '
|
||||
shift 1
|
||||
;;
|
||||
(-R|--replication)
|
||||
opt_recursive='-R'
|
||||
opt_force='-F'
|
||||
shift 1
|
||||
;;
|
||||
(-X|--destroy)
|
||||
opt_destroy='1'
|
||||
shift 1
|
||||
;;
|
||||
(-F|--fallback)
|
||||
opt_fallback='1'
|
||||
shift 1
|
||||
;;
|
||||
(-b|--rollback)
|
||||
opt_force='-F'
|
||||
shift 1
|
||||
;;
|
||||
(--sep)
|
||||
@ -293,10 +524,44 @@ do
|
||||
opt_sep="$2"
|
||||
shift 2
|
||||
;;
|
||||
(--send-full)
|
||||
if [ -n "$opt_sendprefix" ]
|
||||
then
|
||||
print_log error "Only one of --send-incr and --send-full must be specified."
|
||||
exit 139
|
||||
fi
|
||||
opt_sendprefix="$2/"
|
||||
opt_send='full'
|
||||
shift 2
|
||||
;;
|
||||
(--send-incr)
|
||||
opt_sendincr="$2"
|
||||
if [ -n "$opt_sendprefix" ]
|
||||
then
|
||||
print_log error "Only one of --send-incr and --send-full must be specified."
|
||||
exit 140
|
||||
fi
|
||||
opt_sendprefix="$2/"
|
||||
opt_send='incr'
|
||||
shift 2
|
||||
;;
|
||||
(-g|--syslog)
|
||||
opt_syslog='1'
|
||||
shift 1
|
||||
;;
|
||||
(-i|--send-atonce)
|
||||
opt_atonce='-i'
|
||||
shift 1
|
||||
;;
|
||||
(--remove-local)
|
||||
if ! test "$2" -gt '0' 2>/dev/null
|
||||
then
|
||||
print_log error "The $1 parameter must be a positive integer."
|
||||
exit 141
|
||||
fi
|
||||
opt_remove="$2"
|
||||
shift 2
|
||||
;;
|
||||
(-v|--verbose)
|
||||
opt_quiet=''
|
||||
opt_verbose='1'
|
||||
@ -309,6 +574,8 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
|
||||
if [ "$#" -eq '0' ]
|
||||
then
|
||||
print_log error "The filesystem argument list is empty."
|
||||
@ -339,9 +606,19 @@ ZFS_LIST=$(env LC_ALL=C zfs list -H -t filesystem,volume -s name \
|
||||
-o name,com.sun:auto-snapshot,com.sun:auto-snapshot:"$opt_label") \
|
||||
|| { print_log error "zfs list $?: $ZFS_LIST"; exit 136; }
|
||||
|
||||
SNAPSHOTS_OLD=$(env LC_ALL=C zfs list -H -t snapshot -S creation -o name) \
|
||||
|| { print_log error "zfs list $?: $SNAPSHOTS_OLD"; exit 137; }
|
||||
ZFS_LOCAL_LIST=($(echo "$ZFS_LIST" | awk -F'\t' '{ORS="\n"}{print $1}'))
|
||||
|
||||
SNAPSHOTS_OLD_LOC=($(env LC_ALL=C zfs list -H -t snapshot -S creation -o name)) \
|
||||
|| { print_log error "zfs list $?: $SNAPSHOTS_OLD_LOC"; exit 137; }
|
||||
|
||||
if [ "$opt_send" != "no" ]
|
||||
then
|
||||
SNAPSHOTS_OLD_REM=($(eval "$opt_sendtocmd" zfs list -H -t snapshot -S creation -o name | grep "$opt_sendprefix")) \
|
||||
|| { print_log error "zfs list $?: $SNAPSHOTS_OLD_REM"; exit 138; }
|
||||
|
||||
ZFS_REMOTE_LIST=($(eval "$opt_sendtocmd" zfs list -H -t filesystem,volume -s name -o name)) \
|
||||
|| { print_log error "$opt_sendtocmd zfs list $?: $ZFS_REMOTE_LIST"; exit 139; }
|
||||
fi
|
||||
|
||||
# Verify that each argument is a filesystem or volume.
|
||||
for ii in "$@"
|
||||
@ -357,6 +634,21 @@ do
|
||||
exit 138
|
||||
done
|
||||
|
||||
|
||||
|
||||
WAITING=0
|
||||
while [ -f /tmp/"$tmp_file_prefix"* ]; do
|
||||
if [ "$WAITING" -gt 12 ]; then
|
||||
print_log warning "exiting due to lock file ... "
|
||||
exit 555
|
||||
fi
|
||||
print_log warning "sleeping on lock file ... $WAITING"
|
||||
sleep 5
|
||||
let WAITING=WAITING+1
|
||||
done
|
||||
LOCKFILE=`mktemp -t $tmp_file_prefix`
|
||||
|
||||
|
||||
# Get a list of pools that are being scrubbed.
|
||||
ZPOOLS_SCRUBBING=$(echo "$ZPOOL_STATUS" | awk -F ': ' \
|
||||
'$1 ~ /^ *pool$/ { pool = $2 } ; \
|
||||
@ -369,28 +661,30 @@ ZPOOLS_NOTREADY=$(echo "$ZPOOL_STATUS" | awk -F ': ' \
|
||||
$1 ~ /^ *state$/ && $2 !~ /ONLINE|DEGRADED/ { print pool } ' \
|
||||
| sort)
|
||||
|
||||
# Get a list of datasets for which snapshots are explicitly disabled.
|
||||
NOAUTO=$(echo "$ZFS_LIST" | awk -F '\t' \
|
||||
'tolower($2) ~ /false/ || tolower($3) ~ /false/ {print $1}')
|
||||
# Get a list of datasets for which snapshots are not explicitly disabled.
|
||||
CANDIDATES=$(echo "$ZFS_LIST" | awk -F '\t' \
|
||||
'tolower($2) !~ /false/ && tolower($3) !~ /false/ {print $1}')
|
||||
|
||||
# If the --default-exclude flag is set, then exclude all datasets that lack
|
||||
# an explicit com.sun:auto-snapshot* property. Otherwise, include them.
|
||||
if [ -n "$opt_default_exclude" ]
|
||||
then
|
||||
# Get a list of datasets for which snapshots are explicitly enabled.
|
||||
CANDIDATES=$(echo "$ZFS_LIST" | awk -F '\t' \
|
||||
'tolower($2) ~ /true/ || tolower($3) ~ /true/ {print $1}')
|
||||
# Get a list of datasets for which snapshots are not explicitly enabled.
|
||||
NOAUTO=$(echo "$ZFS_LIST" | awk -F '\t' \
|
||||
'tolower($2) !~ /true/ && tolower($3) !~ /true/ {print $1}')
|
||||
else
|
||||
# Invert the NOAUTO list.
|
||||
CANDIDATES=$(echo "$ZFS_LIST" | awk -F '\t' \
|
||||
'tolower($2) !~ /false/ && tolower($3) !~ /false/ {print $1}')
|
||||
# Get a list of datasets for which snapshots are explicitly disabled.
|
||||
NOAUTO=$(echo "$ZFS_LIST" | awk -F '\t' \
|
||||
'tolower($2) ~ /false/ || tolower($3) ~ /false/ {print $1}')
|
||||
fi
|
||||
|
||||
# Initialize the list of datasets that will get a recursive snapshot.
|
||||
TARGETS_RECURSIVE=''
|
||||
declare -a TARGETS_DRECURSIVE
|
||||
declare -a TARGETS_TMP_RECURSIVE
|
||||
|
||||
# Initialize the list of datasets that will get a non-recursive snapshot.
|
||||
TARGETS_REGULAR=''
|
||||
declare -a TARGETS_DREGULAR
|
||||
|
||||
|
||||
for ii in $CANDIDATES
|
||||
do
|
||||
@ -398,12 +692,12 @@ do
|
||||
# Suppose ii=tanker/foo and jj=tank sometime during the loop.
|
||||
# Just testing "$ii" != ${ii#$jj} would incorrectly match.
|
||||
iii="$ii/"
|
||||
|
||||
|
||||
# Exclude datasets that are not named on the command line.
|
||||
IN_ARGS='0'
|
||||
for jj in "$@"
|
||||
do
|
||||
if [ "$jj" = '//' -o "$jj" = "$ii" ]
|
||||
if [ "$jj" = '//' -o "$jj" = "$ii" -o -n "$opt_recursive" -a -z "${ii##$jj/*}" ]
|
||||
then
|
||||
IN_ARGS=$(( $IN_ARGS + 1 ))
|
||||
fi
|
||||
@ -412,7 +706,7 @@ do
|
||||
then
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
# Exclude datasets in pools that cannot do a snapshot.
|
||||
for jj in $ZPOOLS_NOTREADY
|
||||
do
|
||||
@ -445,25 +739,29 @@ do
|
||||
do
|
||||
# Ibid regarding iii.
|
||||
jjj="$jj/"
|
||||
|
||||
|
||||
# The --recursive switch only matters for non-wild arguments.
|
||||
if [ -z "$opt_recursive" -a "$1" != '//' ]
|
||||
then
|
||||
# Snapshot this dataset non-recursively.
|
||||
print_log debug "Including $ii for regular snapshot."
|
||||
TARGETS_REGULAR="${TARGETS_REGULAR:+$TARGETS_REGULAR }$ii" # nb: \t
|
||||
TARGETS_DREGULAR=( ${TARGETS_DREGULAR[@]} $( printf "%s\n" $ii))
|
||||
continue 2
|
||||
# Check whether the candidate name is excluded
|
||||
elif [ "$jjj" = "$iii" ]
|
||||
then
|
||||
continue 2
|
||||
# Check whether the candidate name is a prefix of any excluded dataset name.
|
||||
elif [ "$jjj" != "${jjj#$iii}" ]
|
||||
then
|
||||
# Snapshot this dataset non-recursively.
|
||||
print_log debug "Including $ii for regular snapshot."
|
||||
TARGETS_REGULAR="${TARGETS_REGULAR:+$TARGETS_REGULAR }$ii" # nb: \t
|
||||
TARGETS_DREGULAR=( ${TARGETS_DREGULAR[@]} $( printf "%s\n" $ii))
|
||||
continue 2
|
||||
fi
|
||||
done
|
||||
|
||||
for jj in $TARGETS_RECURSIVE
|
||||
for jj in ${TARGETS_TMP_RECURSIVE[@]}
|
||||
do
|
||||
# Ibid regarding iii.
|
||||
jjj="$jj/"
|
||||
@ -484,7 +782,9 @@ do
|
||||
# * Is not the descendant of an already included filesystem.
|
||||
#
|
||||
print_log debug "Including $ii for recursive snapshot."
|
||||
TARGETS_RECURSIVE="${TARGETS_RECURSIVE:+$TARGETS_RECURSIVE }$ii" # nb: \t
|
||||
TARGETS_TMP_RECURSIVE=( ${TARGETS_TMP_RECURSIVE[@]} $( printf "%s\n" $ii) )
|
||||
#TARGETS_DRECURSIVE=( ${TARGETS_DRECURSIVE[@]} $(printf "%s\n" ${ZFS_LOCAL_LIST[@]} | grep ^$ii) )
|
||||
|
||||
done
|
||||
|
||||
# Linux lacks SMF and the notion of an FMRI event, but always set this property
|
||||
@ -501,22 +801,39 @@ SNAPNAME="$opt_prefix${opt_label:+$opt_sep$opt_label-$DATE}"
|
||||
# The expression for matching old snapshots. -YYYY-MM-DD-HHMM
|
||||
SNAPGLOB="$opt_prefix${opt_label:+?$opt_label}????????????????"
|
||||
|
||||
test -n "$TARGETS_REGULAR" \
|
||||
&& print_log info "Doing regular snapshots of $TARGETS_REGULAR"
|
||||
|
||||
test -n "$TARGETS_RECURSIVE" \
|
||||
&& print_log info "Doing recursive snapshots of $TARGETS_RECURSIVE"
|
||||
test -n "$TARGETS_DREGULAR" \
|
||||
&& print_log info "Doing regular snapshots of ${TARGETS_DREGULAR[@]}"
|
||||
|
||||
test -n "$TARGETS_TMP_RECURSIVE" \
|
||||
&& print_log info "Doing recursive snapshots of ${TARGETS_TMP_RECURSIVE[@]}"
|
||||
|
||||
test -n "$opt_dry_run" \
|
||||
&& print_log info "Doing a dry run. Not running these commands..."
|
||||
|
||||
do_snapshots "$SNAPPROP" "" "$SNAPNAME" "$SNAPGLOB" "$TARGETS_REGULAR"
|
||||
do_snapshots "$SNAPPROP" "-r" "$SNAPNAME" "$SNAPGLOB" "$TARGETS_RECURSIVE"
|
||||
# expand FS list if replication is not used
|
||||
if [ "$opt_recursive" = ' ' ]
|
||||
then
|
||||
for ii in "${TARGETS_TMP_RECURSIVE[@]}"; do TARGETS_DRECURSIVE=( ${TARGETS_DRECURSIVE[@]} $(printf "%s\n" ${ZFS_LOCAL_LIST[@]} | grep ^$ii) ); done
|
||||
else
|
||||
TARGETS_DRECURSIVE=( ${TARGETS_TMP_RECURSIVE[@]} )
|
||||
fi
|
||||
|
||||
if [ "$opt_create" -eq '1' -a "$opt_send" != "no" ]; then
|
||||
do_createfs "${TARGETS_DREGULAR[*]}"
|
||||
do_createfs "${TARGETS_DRECURSIVE[*]}"
|
||||
fi
|
||||
|
||||
do_snapshots "$SNAPPROP" "" "$SNAPNAME" "$SNAPGLOB" "${TARGETS_DREGULAR[*]}"
|
||||
do_snapshots "$SNAPPROP" "$opt_recursive" "$SNAPNAME" "$SNAPGLOB" "${TARGETS_DRECURSIVE[*]}"
|
||||
|
||||
print_log notice "@$SNAPNAME," \
|
||||
"$SNAPSHOT_COUNT created," \
|
||||
"$SNAPSHOT_COUNT created snapshots," \
|
||||
"$DESTRUCTION_COUNT destroyed," \
|
||||
"$CREATION_COUNT created filesystems," \
|
||||
"$WARNING_COUNT warnings."
|
||||
|
||||
rm -f $LOCKFILE
|
||||
|
||||
exit 0
|
||||
# }
|
||||
|
Loading…
Reference in New Issue
Block a user