Last active
September 24, 2023 16:17
-
-
Save neon12345/89968c0a71f064657b33ddd5047b3722 to your computer and use it in GitHub Desktop.
Backup cleanup algorithm test
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
#!/bin/bash | |
# This script will simulate an infinite backup cycle per day. | |
# Empty backup files are created in the current working directory | |
# and deleted acording to the cleanup algorithm parameters. | |
# One file per second is created, which is one simulated day. | |
# => It is best to run this script form inside an empty test directory. | |
# This script will not halt and must be aborted! | |
# The same algorithm is used in https://github.com/bit-team/backintime | |
set -o pipefail | |
KEEP_LAST=2 | |
KEEP_DAY=7 | |
KEEP_WEEK=4 | |
KEEP_MONTH=24 | |
function err() { echo "$@" 1>&2; } | |
function sscanf() { | |
local str="$1" | |
if [[ "$str" =~ ^([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+).inc.backup$ ]]; then | |
HOUR=${BASH_REMATCH[1]} | |
DAY=${BASH_REMATCH[2]} | |
MONTH=${BASH_REMATCH[3]} | |
YEAR=${BASH_REMATCH[4]} | |
WEEK=${BASH_REMATCH[5]} | |
return | |
fi | |
false | |
} | |
function date_ts_from_ymd() { | |
local YEAR="$1" | |
local MONTH="$2" | |
local DAY="$3" | |
date -d "$YEAR-$MONTH-$DAY 00:00:00" "+%s" | |
} | |
function date_from_ts() { | |
local TS="$1" | |
local FORMAT="$2" | |
local OTHER="$3" | |
date -d "$(date -d @$TS "+%Y-%m-%d %H:%M:%S") $OTHER" "$FORMAT" | |
} | |
function date_in_range() { | |
local TS="$1" | |
local MIN="$2" | |
local MAX="$3" | |
(( MIN <= TS && TS < MAX )) | |
} | |
D=0 | |
CURRENT_DATE=$(date "+%s") | |
while true; do | |
D="$(( D + 1 ))" | |
CURRENT_HOUR=$(date_from_ts "$CURRENT_DATE" "+%s" "$D days") | |
CURRENT_DAY=$(date_from_ts "$CURRENT_DATE" "+%d" "$D days") | |
CURRENT_WEEK=$(date_from_ts "$CURRENT_DATE" "+%V" "$D days") | |
CURRENT_MONTH=$(date_from_ts "$CURRENT_DATE" "+%m" "$D days") | |
CURRENT_YEAR=$(date_from_ts "$CURRENT_DATE" "+%Y" "$D days") | |
FILE="$CURRENT_HOUR-$CURRENT_DAY-$CURRENT_MONTH-$CURRENT_YEAR-$CURRENT_WEEK.inc.backup" | |
function date_current_ts() { | |
local OTHER="$1" | |
local FROM="$2" | |
if [[ -z "$FROM" ]]; then | |
FROM="$CURRENT_HOUR" | |
fi | |
date_from_ts "$FROM" "+%s" "$OTHER" | |
} | |
function find_snapshots() { | |
local MIN_YEAR=9999 | |
while IFS= read -r -d $'\0' file; do | |
THE_FILE=$(basename $file) | |
if sscanf "$THE_FILE"; then | |
if (( MIN_YEAR > YEAR )); then | |
MIN_YEAR=$YEAR | |
fi | |
echo "$THE_FILE" | |
fi | |
done < <(find $TARGET_DIR -maxdepth 1 -type f -print0 | sort -Vz) | |
echo $MIN_YEAR | |
} | |
function find_remove() { | |
local TARGET_DIR="$1" | |
local MIN=0 | |
local MAX=0 | |
local CURRENT=0 | |
local CURRENT2=0 | |
local SNAPSHOTS=$(find_snapshots) | |
local MIN_YEAR=0 | |
local KEEP="" | |
local MAP="" | |
declare -A MAP | |
function find_keep() { | |
if (( KEEP_LAST > 0 )); then | |
MIN=$(date_current_ts "$(( KEEP_LAST )) days ago") | |
MAX=$(date_current_ts "1 days") | |
for file in $SNAPSHOTS; do | |
sscanf "$file" | |
if date_in_range $HOUR $MIN $MAX; then | |
echo "$file" | |
fi | |
MIN_YEAR="$file" | |
done | |
fi | |
if (( KEEP_DAY > 0 )); then | |
for (( j=0; j < $KEEP_DAY; j++ )); do | |
MIN=$(date_current_ts "$j days ago") | |
MAX=$(date_current_ts "1 days" $MIN) | |
for file in $SNAPSHOTS; do | |
sscanf "$file" | |
if date_in_range $HOUR $MIN $MAX; then | |
echo "$file" | |
break | |
fi | |
done | |
done | |
fi | |
if (( KEEP_WEEK > 0 )); then | |
local WEEK_DAY=$(date_from_ts $(date_current_ts "") "+%u") | |
CURRENT=$(date_current_ts "$WEEK_DAY days ago") | |
for (( j=0; j < KEEP_WEEK; j++ )); do | |
MIN=$CURRENT | |
MAX=$(date_current_ts "8 days" $MIN) | |
for file in $SNAPSHOTS; do | |
sscanf "$file" | |
if date_in_range $HOUR $MIN $MAX; then | |
echo "$file" | |
break | |
fi | |
done | |
CURRENT=$(date_current_ts "7 days ago" $CURRENT) | |
done | |
fi | |
if (( KEEP_MONTH > 0 )); then | |
CURRENT=$(date_ts_from_ymd "$CURRENT_YEAR" "$CURRENT_MONTH" "1") | |
CURRENT2=$(date_current_ts "1 months" $CURRENT) | |
for (( j=0; j < KEEP_MONTH; j++ )); do | |
MIN=$CURRENT | |
MAX=$CURRENT2 | |
for file in $SNAPSHOTS; do | |
sscanf "$file" | |
if date_in_range $HOUR $MIN $MAX; then | |
echo "$file" | |
break | |
fi | |
done | |
CURRENT2=$CURRENT | |
CURRENT=$(date_current_ts "1 months ago" $CURRENT) | |
done | |
fi | |
for (( j=MIN_YEAR; j <= CURRENT_YEAR; j++ )); do | |
MIN=$(date_ts_from_ymd "$j" "1" "1") | |
MAX=$(date_ts_from_ymd "$(( j + 1))" "1" "1") | |
for file in $SNAPSHOTS; do | |
sscanf "$file" | |
if date_in_range $HOUR $MIN $MAX; then | |
echo "$file" | |
break | |
fi | |
done | |
done | |
} | |
KEEP=$(find_keep | sort -u) | |
for file in $KEEP; do | |
MAP["$file"]=1 | |
done | |
for file in $SNAPSHOTS; do | |
if [[ ${MAP["$file"]} != 1 ]]; then | |
if (( ${#file} > 10 )); then | |
echo "$file" | |
fi | |
fi | |
done | |
} | |
OUT_FILE="$FILE" | |
if [[ -f "$OUT_FILE" ]]; then | |
err "$FILE exists, try later." | |
exit 1 | |
fi | |
#date_from_ts $(date_current_ts "") "+%Y-%m-%d %H:%M:%S" | |
#date_from_ts $(date_current_ts "1 months") "+%Y-%m-%d %H:%M:%S" | |
#echo "add $OUT_FILE" | |
touch "$OUT_FILE" | |
TO_REMOVE=$(find_remove .) | |
for line in $TO_REMOVE; do | |
#echo "remove: $line" | |
rm "$line" | |
done | |
sleep 1 | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment