-
Notifications
You must be signed in to change notification settings - Fork 1
/
snapclean.sh
executable file
·200 lines (179 loc) · 5.44 KB
/
snapclean.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/bin/bash
SCRIPTNAME=$(basename $0)
SCRIPTDIR=$(dirname $0)
# Default settings for retention scheme
DOW="Sunday" # which weekday must be kept
MAXWEEK=4 # how many weekdays must be kept
MAXDAY=7 # how many days must be kept
MAXHOUR=1 # how many hours must be kept: MAXHOUR*24 hours
# Get env var if given
DOW="${SNAPSYNC_DOW:-$DOW}"
MAXWEEK="${SNAPSYNC_MAXWEEK:-$MAXWEEK}"
MAXDAY="${SNAPSYNC_MAXDAY:-$MAXDAY}"
MAXHOUR="${SNAPSYNC_MAXHOUR:-$MAXHOUR}"
# Ya gotta have limits!
WEEKDAYS="Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
MAX_MAXWEEK=52 # one year
MAX_MAXDAY=365 # one year
MAX_MAXHOUR=168 # one week
# Check if var is in list
function exists_in_list() {
LIST=$1
DELIMITER=$2
VALUE=$3
[[ "$LIST" =~ ($DELIMITER|^)$VALUE($DELIMITER|$) ]]
}
if ! exists_in_list "$WEEKDAYS" " " $DOW ; then
echo "Error: DOW is not in list [$WEEKDAYS]" >&2; exit 1
fi
# Check if var is number
re='^[0-9]+$'
if ! [[ $MAXWEEK =~ $re ]] ; then
echo "Error: MAXWEEK is not a number" >&2; exit 1
else
if ! [ "$MAXWEEK" -ge 0 ] && [ "$MAXWEEK" -le "$MAX_MAXWEEK" ] ; then
echo "Error: MAXWEEK is not in range [0-$MAX_MAXWEEK]" >&2; exit 1
fi
fi
if ! [[ $MAXDAY =~ $re ]] ; then
echo "Error: MAXDAY is not a number" >&2; exit 1
else
if ! [ "$MAXDAY" -ge 0 ] && [ "$MAXDAY" -le "$MAX_MAXDAY" ] ; then
echo "Error: MAXWEEK is not in range [0-$MAX_MAXDAY]" >&2; exit 1
fi
fi
if ! [[ $MAXHOUR =~ $re ]] ; then
echo "Error: MAXHOUR is not a number" >&2; exit 1
else
if ! [ "$MAXHOUR" -ge 0 ] && [ "$MAXHOUR" -le "$MAX_MAXHOUR" ] ; then
echo "Error: MAXHOUR is not in range [0-$MAX_MAXHOUR]" >&2; exit 1
fi
fi
function usage {
echo "$SCRIPTNAME"
echo ""
echo "usage: $SCRIPTNAME <SNAPSYNC DIR>"
echo " <SNAPSYNC DIR> location where all backups are stored"
echo ""
echo "description: Cleanup snapsync backups according to retention scheme"
echo ""
echo "With every call of $SCRIPTNAME the snapsync directory is cleaned up"
echo "according to the retention scheme. Only the following snapshots are kept:"
echo "1. the oldest one"
echo "2. the first backup in a month"
echo "3. the first backup on every $DOW [SNAPSYNC_DOW] of the last $MAXWEEK [SNAPSYNC_MAXWEEK] weeks"
echo "4. Every first backup of the last $MAXDAY [SNAPSYNC_MAXDAY] days"
echo "5. Every backup in the last $(echo $MAXHOUR*24 | bc) [SNAPSYNC_MAXHOUR] hours"
echo "note: the retention scheme can be easily modified using the environment"
echo "variables shown in square brackets."
}
if [ $# != 1 ];
then
usage
exit 1
fi
PREFIX=$(realpath $1)
if ! [ -d $PREFIX ] ; then
echo "Error: snapsync directory $PREFIX does not exist" >&2; exit 1
fi
LCK=$PREFIX/lock
MDB=$PREFIX/mlocate.db
# determine laptime and echo result
# $1 = start time for lap
# $2 = activity for echo result
function echo_lap() {
LOCLAP=`date +%s`
SEC=`echo $LOCLAP-$1 | bc`
TIME=`date -d "1970-1-1 +$SEC seconds" +%T`
echo "Done $2 in $TIME"
LAP=$LOCLAP
}
START=`date +%s`
echo "Starting $SCRIPTNAME"
date -R
if [ -e $LCK ]; then
DATE=`date -r $LCK`
SCRIPT=`cat $LCK`
echo "Error: lockfile $LCK exists! Most likely the $SCRIPT script is already running." >&2
echo " This lockfile is created on: $DATE" >&2
exit 1
else
echo $SCRIPTNAME > $LCK
fi
# first backup ever
cd $PREFIX
first=`ls -rd 2* | tail -1`
# MONTHS, keep every first backup of the month (NOTE: including the oldest!)
i=0
cont=1
findstr=""
while [ "$cont" = "1" ]; do
datestr=`date --date "now -$i month" +"%Y%m"`
if [ "$datestr" -ge "${first:0:6}" ]; then
month=`find . -maxdepth 1 -mindepth 1 -name "$datestr*" -type d -printf "%f\n"| sort | head -1`
if [ "$month" != "" ]; then
findstr=$(echo $findstr " ! -name $month")
fi
i=$(echo "$i + 1" | bc)
else
cont=0
fi
done
# WEEKS, keep last $MAXWEEK weekdays ($DOW)
nowstr=`date +"%Y%m%d"`
i=0
cont=1
noweeks=0
while [ "$cont" = "1" ]; do
datestr=`date --date "now -$i week $DOW" +"%Y%m%d"`
if [ "$datestr" -ge "${first:0:8}" ]; then
if [ "$datestr" -le "$nowstr" ]; then
week=`find . -maxdepth 1 -mindepth 1 -name "$datestr*" -type d -printf "%f\n" | sort | head -1`
noweeks=$(echo "$noweeks + 1" | bc)
if [ "$noweeks" = "$MAXWEEK" ]; then
cont=0
fi
if [ "$week" != "" ]; then
findstr=$(echo $findstr " ! -name $week")
fi
fi
i=$(echo "$i + 1" | bc)
else
cont=0
fi
done
# DAYS, keep last $MAXDAY days
nowstr=`date +"%Y%m%d"`
i=0
cont=1
nodays=0
while [ "$cont" = "1" ]; do
datestr=`date --date "now -$i day" +"%Y%m%d"`
if [ "$datestr" -ge "${first:0:8}" ]; then
if [ "$datestr" -le "$nowstr" ]; then
day=`find . -maxdepth 1 -mindepth 1 -name "$datestr*" -type d -printf "%f\n" | sort | head -1`
nodays=$(echo "$nodays + 1" | bc)
if [ "$nodays" = "$MAXDAY" ]; then
cont=0
fi
if [ "$day" != "" ]; then
findstr=$(echo $findstr " ! -name $day")
fi
fi
i=$(echo "$i + 1" | bc)
else
cont=0
fi
done
# HOURS, keep last $MAXHOUR*24 hours
findstr=$(echo $findstr " ! -mtime -$MAXHOUR")
echo "Removing:"
find . -maxdepth 1 -mindepth 1 -type d $findstr -printf "%f\n" -exec rm -rf {} \;
#echo $findstr
#find . -maxdepth 1 -mindepth 1 -type d $findstr -printf "%f\n"
echo_lap $START "cleaning up"
updatedb --database-root $PREFIX --require-visibility 0 --output $MDB
echo_lap $LAP "updating mlocate.db"
echo_lap $START "total script"
echo "============================"
rm -f $LCK