Skip to content

Instantly share code, notes, and snippets.

@ejpcmac
Last active February 19, 2023 13:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ejpcmac/501cb368c72976029845679a2704e758 to your computer and use it in GitHub Desktop.
Save ejpcmac/501cb368c72976029845679a2704e758 to your computer and use it in GitHub Desktop.
Clean old ZFS auto-snapshots on backup destinations
#!/bin/sh
filter_snapshots() {
echo "$1" | grep $2 | tac | tail -n +$(($3 + 1)) | sed 's/.*@//' | sed -z 's/\n/,/g'
}
if [ $# -ne 6 ]; then
echo "usage: $0 <dataset> <frequent> <hourly> <daily> <weekly> <monthly>"
exit 1
fi
for dataset in $(zfs list -r -o name $1 | tail -n +2); do
printf "\e[32m=> Cleaning up snapshots for $dataset\e[0m\n"
snapshots=$(zfs list -t snapshot -o name $dataset)
# Remove “system” snapshots.
valid_state=$(filter_snapshots "$snapshots" valid-state 0)
update=$(filter_snapshots "$snapshots" update 0)
sys_snaps=$valid_state$update
# Remove manual syncoid snapshots.
manual_saturne=$(filter_snapshots "$snapshots" syncoid_saturne_2 0)
manual_helios=$(filter_snapshots "$snapshots" syncoid_helios_2 0)
manual_nixos=$(filter_snapshots "$snapshots" syncoid_nixos_2 0)
manual=$manual_saturne$manual_helios$manual_nixos
# Keep only one syncoid snapshot per backup pool.
old_helios=$(filter_snapshots "$snapshots" syncoid_helios_saturne 1)
old_titan=$(filter_snapshots "$snapshots" syncoid_titan_saturne 1)
old_tethys=$(filter_snapshots "$snapshots" syncoid_tethys_saturne 1)
old_backup=$old_helios$old_titan$old_tethys
# Keep auto-snapshots as configured.
old_frequent=$(filter_snapshots "$snapshots" frequent $2)
old_hourly=$(filter_snapshots "$snapshots" hourly $3)
old_daily=$(filter_snapshots "$snapshots" daily $4)
old_weekly=$(filter_snapshots "$snapshots" weekly $5)
old_monthly=$(filter_snapshots "$snapshots" monthly $6)
old_auto=$old_frequent$old_hourly$old_daily$old_weekly$old_monthly
old_snapshots=$(echo $sys_snaps$manual$old_backup$old_auto | sed 's/.$//')
if [ "$old_snapshots" != "" ]; then
zfs destroy -v $dataset@$old_snapshots
fi
done
@rub2012
Copy link

rub2012 commented May 3, 2022

thanks you. This is exactly what I was needing!

@ejpcmac
Copy link
Author

ejpcmac commented Feb 19, 2023

Hello @rub2012, glad it helped you! I’ve just updated it with the version I am currently using, which adds the following:

  • Cleanup manual syncoid snapshots done from a few hosts (you’ll want to update the filters)
  • Cleanup syncoid snapshots from other backup pools, keeping 1
  • Pass the number of auto-snapshots to keep as arguments
  • Optimise the cleanup time by running zfs list -t snapshot only once per dataset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment