-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrotating_folder_backup
executable file
·173 lines (138 loc) · 5.09 KB
/
rotating_folder_backup
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
#!/usr/bin/env python3
'''
rotating_folder_backup
Copyright 2022-2023 Angel Leon.
Author: @gubatron
Easily backup folders as .tgz files, automatically removing older backups.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
'''
import os
import shutil
import time
import argparse
def zeroPad(number):
number = int(number)
if number < 10:
return '0'+str(number)
return str(number)
def getOldBackups(backups_dir_path, max_days_to_keep):
"""
Retrieve a list of paths that are considered old
"""
MAX_AGE_IN_SECONDS = 24*60*60*int(max_days_to_keep)
old_backups = []
backups = os.listdir(backups_dir_path)
for backup in backups:
backup_full_path = backups_dir_path + os.path.sep + backup
last_modified = os.path.getmtime(backup_full_path)
age = time.time() - last_modified
if age > MAX_AGE_IN_SECONDS:
old_backups.append(backup_full_path)
return old_backups
def backupTGZ(backup_name, backup_source_path, backup_destination_path):
"""
Given a backup_name, backup source path (usually a folder e.g. /var/lib/mysql) this will
copy the source folder or source file into the backup_destination_path
tar it, gzip it under
backup_destination_path/backup_name.YYYY-MM-DD-at-HH-MM.tar.gz
If you invoke for example
backupTGZ('mysql','/var/lib/mysql','/mnt/mysql_backups')
You will end up with
/mnt/mysql_backups/mysql.2013-12-24-at-22-34-59.tar.gz
"""
# remove trailing slashes off everything
(backup_name, backup_source_path, backup_destination_path) = [x.rstrip(
'/') for x in (backup_name, backup_source_path, backup_destination_path)]
t = time.gmtime()
untarred_destination_name = backup_name + '.' + str(t[0]) + '-' + str(zeroPad(t[1])) + '-' + str(
zeroPad(t[2])) + '-at-' + zeroPad(t[3]) + '-' + zeroPad(t[4]) + '-' + zeroPad(5)
cmd = 'cp -R -a ' + backup_source_path + ' ' + \
backup_destination_path + os.path.sep + untarred_destination_name
cmd += ' && '
cmd += 'tar cvfz ' + untarred_destination_name + '.tar.gz ' + \
backup_destination_path + os.path.sep + untarred_destination_name + os.path.sep
cmd += ' && '
cmd += 'mv ' + untarred_destination_name + \
'.tar.gz ' + backup_destination_path + os.path.sep
cmd += ' && '
cmd += 'chmod 777 ' + backup_destination_path + \
os.path.sep + untarred_destination_name + '.tar.gz'
cmd += ' && '
cmd += 'rm -fr ' + backup_destination_path + \
os.path.sep + untarred_destination_name
cmd += ' ;'
print(cmd)
os.system(cmd)
def initialize_arg_parser(arg_parser):
arg_parser.add_argument(
'--backup-name',
'-n',
type=str,
help='The prefix name of the resulting .tgz file',
required=True
)
arg_parser.add_argument(
'--source-folder',
'-s',
type=str,
help='The source folder you want to backup',
required=True
)
arg_parser.add_argument(
'--target-folder',
'-t',
type=str,
help='The target folder where backups will be stored',
required=True
)
arg_parser.add_argument(
"--days",
"-d",
default=7,
type=int,
help="How many days you want to keep a backup until removing it on the next invocation. (Default is 7 days)"
)
def validate_arguments(args) -> bool:
if not os.path.isdir(args.source_folder):
print(
f"\n\nInvalid source folder. {args.source_folder} does not exist\n\n")
return False
if not os.path.isdir(args.target_folder):
print(
f"\n\nInvalid target folder. {args.target_folder} does not exist\n\n")
return False
return True
def remove_trailing_slashes_in_folders(args):
while args.source_folder.endswith('/'):
args.source_folder = args.source_folder[:-1]
while args.target_folder.endswith('/'):
args.target_folder = args.target_folder[:-1]
def main():
arg_parser = argparse.ArgumentParser()
initialize_arg_parser(arg_parser)
print()
args, _ = arg_parser.parse_known_args()
if not validate_arguments(args):
arg_parser.print_help()
print()
return
remove_trailing_slashes_in_folders(args)
backupTGZ(args.backup_name, args.source_folder, args.target_folder)
old_ones = getOldBackups(args.target_folder, args.days)
if len(old_ones) > 0:
for x in old_ones:
print(f"removing -> {x}\n")
if os.path.isfile(x):
os.remove(x)
elif os.path.isdir(x):
shutil.rmtree(x)
if __name__ == '__main__':
main()