#!/bin/bash set -e set -o pipefail default_retain_years=7 retain_years= # TODO: read retain_years from .propagation use_clock_time= # Delete according to clock time (WARNING: eventually deletes all data) # Never edit this glob. # Generated via: date -Ins | sed 's/[0-9]/[0-9]/g' datetime_glob='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]:[0-9][0-9]' snapshot_prefix='.snapshot~' main() { delete= if [ "$1" = --delete ] then delete=$1 shift fi [ $# = 1 ] || exit case "$1" in /*) ;; *) exit 1 ;; esac cd "$1" || exit find . -maxdepth 1 -type d -name "$snapshot_prefix""$datetime_glob" -print0 | sort -zrn | retain } is_readonly_subvolume() { [ -d "$1" ] if ! 2>/dev/null btrfs subvolume show -- "$1" | sed -En -e'/^\tFlags:.*\breadonly\b/{q0}' -e'${q1}' then return $? fi } btrfs_subvolume_delete() { if [ "$delete" = --delete ] then btrfs subvolume delete "$@" else >&2 echo btrfs subvolume delete "$@" fi } # Delete all snapshots that we do not retain. # The retention period is specified in a ".propagation" file. # If not specified it is 7 years. # Retain the most recent snapshot within any year of the last 7 years. # Retain the most recent snapshot within any month of the last 365 days. # Retain the most recent snapshot within any day of the last 15 days. # Retain the most recent snapshot within any hour of the last 24 hours. # Retain the most recent snapshot within any minute of the last hour. # Retain any snapshot created in the last minute. retain() { 2>/dev/null [ "$retain_years" -ge 1 ] || retain_years=$default_retain_years _year= _month= _day= _hour= _minute= _second= _nanosecond= now= first=y if [ "$use_clock_time" ] then now=$(date +%s) fi while read -d '' line do is_readonly_subvolume "$line" || break dateline=${line#*/"$snapshot_prefix"} [ "$dateline" != "$line" ] before=$(date -d "$dateline" +%s) [ "$now" ] || now=$before age=$((now - before)) IFS='~-T:,' read year month day hour minute second nanosecond <<< "$dateline" keep= if [ "$first" ] then keep="latest -> $line" first= elif [ "$year" != "$_year" ] && [ "$age" -lt $((retain_years * 366 * 24 * 60 * 60)) ] then keep="$year -> $line" elif [ "$month" != "$_month" ] && [ "$age" -lt $((366 * 24 * 60 * 60)) ] then keep="$year-$month -> $line" elif [ "$day" != "$_day" ] && [ "$age" -lt $((15 * 24 * 60 * 60)) ] then keep="$year-$month-$day -> $line" elif [ "$hour" != "$_hour" ] && [ "$age" -lt $((24 * 60 * 60)) ] then keep="$year-$month-${day}T$hour -> $line" elif [ "$minute" != "$_minute" ] && [ "$age" -lt $((60 * 60)) ] then keep="$year-$month-${day}T$hour:$minute -> $line" elif [ "$age" -lt 60 ] then keep="recent -> $line" fi if [ "$keep" ] then (set -- $keep printf '%-20s -> %s\n' "$1" "$3" >&2) else btrfs_subvolume_delete -- "$line" fi _year=$year _month=$month _day=$day _hour=$hour _minute=$minute _second=$second done } main "$@"