From a002492cc53c77e0435e957f86aa546f4ce2d1b0 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 24 May 2023 11:35:12 -0400 Subject: rename --- retain-snapshots | 108 --------------------------------------------------- retention.bash | 71 --------------------------------- src/retain-snapshots | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 179 deletions(-) delete mode 100755 retain-snapshots delete mode 100755 retention.bash create mode 100755 src/retain-snapshots diff --git a/retain-snapshots b/retain-snapshots deleted file mode 100755 index 86f0120..0000000 --- a/retain-snapshots +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash -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 regex. -# Generated via: date -Ins | sed 's/[0-9]/[0-9]/g' -datetime_regexp='[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() -{ - [ $# = 1 ] || exit - case "$1" in - /*) ;; - *) exit 1 ;; - esac - - # Using `cd "$1"` and `find .` allows the path to contain - # newlines, while simple `find "$1"` would break the script. - # NB: Our snapshot name itself never contains whitespace. - cd "$1" || exit - find . -maxdepth 1 -type d -name "$snapshot_prefix""$datetime_regexp" | sort -rn | retain -} - -is_readonly_subvolume() -{ - [ -d "$1" ] - btrfs subvolume show -- "$1" | sed -En -e'/^\tFlags:.*\breadonly\b/{q0}' -e'${q1}' -} - -btrfs_subvolume_delete() -{ - >&2 echo btrfs subvolume delete "$@" -} - -# 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 7 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= - if [ "$use_clock_time" ] - then - now=$(date +%s) - fi - while read 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 [ "$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 $((7 * 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 - echo "$keep" >&2 - else - btrfs_subvolume_delete -- "$line" - fi - - _year=$year - _month=$month - _day=$day - _hour=$hour - _minute=$minute - _second=$second - done -} - -main "$@" diff --git a/retention.bash b/retention.bash deleted file mode 100755 index 149bc7a..0000000 --- a/retention.bash +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -datetime_regexp='[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]' - -main() -{ - [ $# = 1 ] || exit - case "$1" in - /*) ;; - *) exit 1 ;; - esac - - find "$1" -maxdepth 1 -type d -name '.snapshot~'"$datetime_regexp" | sort -n | retain -} - -is_readonly_subvolume() -{ - return 0 - btrfs subvolume show -- "$1" | egrep -q '^ Flags:.*\breadonly\b' -} - -retain() -{ - _year= _month= _day= _hour= _minute= _second= _nanosecond= - now=$(date +%s) - while read line - do - dateline=${line#*/.snapshot~} - before=$(date -d "$dateline" +%s) - age=$((now - before)) - - IFS='~-T:,' read year month day hour minute second nanosecond <<< "$dateline" - - keep= - if [ "$year" != "$_year" ] - then - keep="$year -> $line" - elif [ "$month" != "$_month" ] && [ "$age" -lt $((365 * 24 * 60 * 60)) ] - then - keep="$year-$month -> $line" - elif [ "$day" != "$_day" ] && [ "$age" -lt $((7 * 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 - echo "$keep" >&2 - else - btrfs subvolume delete "$line" - fi - - _year=$year - _month=$month - _day=$day - _hour=$hour - _minute=$minute - _second=$second - done -} - -main "$@" diff --git a/src/retain-snapshots b/src/retain-snapshots new file mode 100755 index 0000000..86f0120 --- /dev/null +++ b/src/retain-snapshots @@ -0,0 +1,108 @@ +#!/bin/bash +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 regex. +# Generated via: date -Ins | sed 's/[0-9]/[0-9]/g' +datetime_regexp='[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() +{ + [ $# = 1 ] || exit + case "$1" in + /*) ;; + *) exit 1 ;; + esac + + # Using `cd "$1"` and `find .` allows the path to contain + # newlines, while simple `find "$1"` would break the script. + # NB: Our snapshot name itself never contains whitespace. + cd "$1" || exit + find . -maxdepth 1 -type d -name "$snapshot_prefix""$datetime_regexp" | sort -rn | retain +} + +is_readonly_subvolume() +{ + [ -d "$1" ] + btrfs subvolume show -- "$1" | sed -En -e'/^\tFlags:.*\breadonly\b/{q0}' -e'${q1}' +} + +btrfs_subvolume_delete() +{ + >&2 echo btrfs subvolume delete "$@" +} + +# 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 7 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= + if [ "$use_clock_time" ] + then + now=$(date +%s) + fi + while read 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 [ "$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 $((7 * 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 + echo "$keep" >&2 + else + btrfs_subvolume_delete -- "$line" + fi + + _year=$year + _month=$month + _day=$day + _hour=$hour + _minute=$minute + _second=$second + done +} + +main "$@" -- cgit v1.2.3