Created
June 27, 2019 21:17
-
-
Save sandhose/bd7610b00b1395045c1566a86469a6a0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!zsh | |
set -auo pipefail | |
# Save the current timestamp to compare dates later | |
local -i ts=$(date -j -f '%H:%M:%S' '00:00:00' '+%s') | |
# The name of the zfs property to check on datasets | |
local property=custom:prune-snapshot | |
local -a datasets=( | |
$(zfs list -H -o name,$property | awk -F '\t' -v value=true '$2 ~ value { print $1 }') | |
) | |
for dataset ($datasets) { | |
local -aU to_delete=() # List of snapshots to delete | |
local -aU kept=() # List of snapshots that have been kept | |
local -a snapshots=( | |
$(zfs list -H -d 1 -t snapshot -o name $dataset | awk -F '@' '{ print $2 }') | |
) | |
for snapshot ($snapshots) { | |
# First decompose the snapshot name and compute the delta | |
local -i year=${snapshot[1,4]} | |
local -i month=${snapshot[5,6]} | |
local -i quarter=$(((month / 4) + 1)) | |
local -i day=${snapshot[7,8]} | |
local -i timestamp=$(date -j -f '%Y %m %d %H:%M:%S' "$year $month $day 00:00:00" '+%s') | |
local -i week=$(date -j -f '%s' $timestamp '+%U') | |
local -i diff=$(((ts - timestamp) / 60 / 60 / 24)) # Diff between the two timestamps in days | |
local -i has_day=0 has_week=0 has_month=0 has_quarter=0 has_year=0 delete=0 | |
# Check if there is already a {yearly,quarterly,monthly,weekly,daily} snapshot | |
if (( ${kept[(I)$year]} )) { has_year=1 } | |
if (( ${kept[(I)$year-Q$quarter]} )) { has_quarter=1 } | |
if (( ${kept[(I)$year-$month]} )) { has_month=1 } | |
if (( ${kept[(I)$year-W$week]} )) { has_week=1 } | |
if (( ${kept[(I)$year-$month-$day]} )) { has_day=1 } | |
local s=( | |
dataset=$dataset | |
snapshot=$snapshot | |
has_day=$has_day | |
has_week=$has_week | |
has_month=$has_month | |
has_quarter=$has_quarter | |
has_year=$has_year | |
) | |
if (($diff < 7)) { | |
s+=(delete=$delete) | |
echo $s: less than a week >&2 | |
} elif (($diff < 60)) { | |
if (($has_day)) { | |
delete=1 | |
} | |
s+=(delete=$delete) | |
echo $s: less than two months >&2 | |
} elif (($diff < 120)) { | |
if (($has_week)) { | |
delete=1 | |
} | |
s+=(delete=$delete) | |
echo $s: less than four months >&2 | |
} elif (($diff < (365 * 3))) { | |
if (($has_month)) { | |
delete=1 | |
} | |
s+=(delete=$delete) | |
echo $s: less than three years >&2 | |
} elif (($diff < (365 * 10))) { | |
if (($has_quarter)) { | |
delete=1 | |
} | |
s+=(delete=$delete) | |
echo $s: less than ten years >&2 | |
} else { | |
if (($has_year)) { | |
delete=1 | |
} | |
s+=(delete=$delete) | |
echo $s: more than ten years >&2 | |
} | |
if (($delete)) { | |
to_delete+=($snapshot) | |
} else { | |
kept+=($year $year-W$week $year-$month $year-Q$quarter $year-$month-$day) | |
} | |
} | |
local -a s=( | |
dataset=$dataset | |
to_delete_count=${#to_delete} | |
) | |
if (( ${#to_delete} > 0 )) { | |
echo "$s: Deleting ${#to_delete}" >&2 | |
zfs destroy -d $dataset@${(j:,:)to_delete} | |
} else { | |
echo "$s: Nothing to do" >&2 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment