rearrange zpool args, style

This commit is contained in:
Dave Eddy 2021-12-04 17:37:24 -05:00
parent 547d01009e
commit f1be6dc83d
1 changed files with 79 additions and 66 deletions

View File

@ -10,61 +10,62 @@ VERSION='v1.4.0'
usage() { usage() {
local prog=${0##*/} local prog=${0##*/}
cat <<-EOF cat <<EOF
usage: $prog [-hnliqRvV] [-p <prefix>] [-s <suffix>] <time> [[dataset1] ...] usage: $prog [-hnliqRvV] [-p <prefix>] [-s <suffix>] <time> [[dataset1] ...]
remove snapshots from one or more zpools that match given criteria remove snapshots from one or more zpools that match given criteria
examples examples
# $prog 1w # $prog 1w
remove snapshots older than a week across all zpools remove snapshots older than a week across all zpools
# $prog -vn 1w # $prog -vn 1w
same as above, but with increased verbosity and without same as above, but with increased verbosity and without
actually deleting any snapshots (dry-run) actually deleting any snapshots (dry-run)
# $prog 3w tank1 tank2/backup # $prog 3w tank1 tank2/backup
remove snapshots older than 3 weeks on tank1 and tank2/backup. remove snapshots older than 3 weeks on tank1 and tank2/backup.
note that this script will recurse through *all* of tank1 and note that this script will recurse through *all* of tank1 and
*all* datasets below tank2/backup *all* datasets below tank2/backup
# $prog -p 'autosnap_' 1M zones # $prog -p 'autosnap_' 1M zones
remove snapshots older than a month on the zones pool that start remove snapshots older than a month on the zones pool that start
with the string "autosnap_" with the string "autosnap_"
# $prog -s '_frequent' 2M tank # $prog -s '_frequent' 2M tank
remove snapshots older than two months on the tank pool that end remove snapshots older than two months on the tank pool that end
with the string "_frequent" with the string "_frequent"
# $prog -i -p 'autosnap_' 1M zones # $prog -i -p 'autosnap_' 1M zones
remove snapshots older than a month on the zones pool that do not remove snapshots older than a month on the zones pool that do not
start with the string "autosnap_" start with the string "autosnap_"
timespec timespec
the first argument denotes how old a snapshot must be for it to the first argument denotes how old a snapshot must be for it to
be considered for deletion - possible specifiers are be considered for deletion - possible specifiers are
s seconds s seconds
m minutes m minutes
h hours h hours
d days d days
w weeks w weeks
M months M months
y years y years
options options
-h print this message and exit -h print this message and exit
-n dry-run, don't actually delete snapshots -n dry-run, don't actually delete snapshots
-l list only mode, just list matching snapshots names -l list only mode, just list matching snapshots names
without deleting (like dry-run mode with machine-parseable output) without deleting (like dry-run mode with machine-parseable
-p <prefix> snapshot prefix string to match output)
-s <suffix> snapshot suffix string to match -p <prefix> snapshot prefix string to match
-i invert matching of prefix and suffix -s <suffix> snapshot suffix string to match
-q quiet, do not printout removed snapshots -i invert matching of prefix and suffix
-R recursively delete, pass '-R' directly to 'zfs destroy' -q quiet, do not printout removed snapshots
-v increase verbosity -R recursively delete, pass '-R' directly to 'zfs destroy'
-V print the version number and exit -v increase verbosity
EOF -V print the version number and exit
EOF
} }
debug() { debug() {
@ -144,6 +145,7 @@ human-time() {
echo '0 seconds' echo '0 seconds'
} }
# convert bytes to a human-readable string
human-size() { human-size() {
local bytes=$1 local bytes=$1
@ -225,6 +227,7 @@ code=0
totalused=0 totalused=0
numsnapshots=0 numsnapshots=0
humanpools=${pools[*]} humanpools=${pools[*]}
humanpools=${humanpools:-<all>}
if $recursive; then if $recursive; then
destroyargs+=('-R') destroyargs+=('-R')
@ -243,40 +246,50 @@ fi
# first pass of the pools (to calculate totals and filter unwanted datasets # first pass of the pools (to calculate totals and filter unwanted datasets
lines=() lines=()
while read -r line; do while read -r line; do
read -r creation snapshot used _ <<< "$line" read -r creation used snapshot _ <<< "$line"
# ensure optional prefix matches # ensure optional prefix matches
snapname=${snapshot#*@} snapname=${snapshot#*@}
if $invert; then if [[ -n $prefix ]]; then
if [[ -n $prefix && $prefix == "${snapname:0:${#prefix}}" ]]; then match=false
debug "skipping $snapshot: does match prefix $prefix" if [[ $prefix == "${snapname:0:${#prefix}}" ]]; then
match=true
fi
if $invert && $match; then
debug "skipping $snapshot: does match prefix '$prefix'"
continue continue
fi fi
else
if [[ -n $prefix && $prefix != "${snapname:0:${#prefix}}" ]]; then if ! $invert && ! $match; then
debug "skipping $snapshot: doesn't match prefix $prefix" debug "skipping $snapshot: doesn't match prefix '$prefix'"
continue continue
fi fi
fi fi
# ensure optional suffix matches # ensure optional suffix matches
if $invert; then if [[ -n $suffix ]]; then
if [[ -n $suffix && $suffix == "${snapname: -${#suffix}}" ]]; then match=false
debug "skipping $snapshot: does match suffix $suffix" if [[ $suffix == "${snapname: -${#suffix}}" ]]; then
match=true
fi
if $invert && $match; then
debug "skipping $snapshot: does match suffix '$suffix'"
continue continue
fi fi
else
if [[ -n $suffix && $suffix != "${snapname: -${#suffix}}" ]]; then if ! $invert && ! $match; then
debug "skipping $snapshot: doesn't match suffix $suffix" debug "skipping $snapshot: doesn't match suffix '$suffix'"
continue continue
fi fi
fi fi
# ensure snapshot is older than the cutoff time # ensure snapshot is older than the cutoff time
delta=$((now - creation)) delta=$((now - creation))
humantime=$(human-time "$delta") ht=$(human-time "$delta")
if ((delta <= seconds)); then if ((delta <= seconds)); then
debug "skipping $snapshot: $humantime old" debug "skipping $snapshot: $ht old"
continue continue
fi fi
@ -289,7 +302,7 @@ while read -r line; do
((totalused += used)) ((totalused += used))
((numsnapshots++)) ((numsnapshots++))
lines+=("$line") lines+=("$line")
done < <(zfs list -Hpo creation,name,used -t snapshot -r "${pools[@]}") done < <(zfs list -Hpo creation,used,name -t snapshot -r "${pools[@]}")
# finish if running with `-l` # finish if running with `-l`
if $listonly; then if $listonly; then
@ -299,24 +312,24 @@ fi
humantotal=$(human-size "$totalused") humantotal=$(human-size "$totalused")
echo "found $numsnapshots snapshots ($humantotal) on pools: ${humanpools:-<all>}" echo "found $numsnapshots snapshots ($humantotal) on pools: $humanpools"
# process snapshots found # process snapshots found
i=0 i=0
for line in "${lines[@]}"; do for line in "${lines[@]}"; do
read -r creation snapshot used _ <<< "$line" read -r creation used snapshot _ <<< "$line"
((i++)) ((i++))
delta=$((now - creation)) delta=$((now - creation))
humantime=$(human-time "$delta") ht=$(human-time "$delta")
humanused=$(human-size "$used") hu=$(human-size "$used")
if $dryrun; then if $dryrun; then
echo -n '[dry-run] ' echo -n '[dry-run] '
fi fi
echo "[$i/$numsnapshots] removing $snapshot: $humantime old ($humanused)" echo "[$i/$numsnapshots] removing $snapshot: $ht old ($hu)"
if ! $dryrun; then if ! $dryrun; then
zfs destroy "${destroyargs[@]}" "$snapshot" || code=1 zfs destroy "${destroyargs[@]}" "$snapshot" || code=1