· 8 years ago · May 27, 2018, 08:04 PM
1# -*- coding: utf-8 -*-
2
3import datetime
4import getopt
5import sys
6import os
7from optparse import OptionParser
8
9#------------------------------------------------------------------------------
10#------------------------- БЛОК ОСÐОВÐЫХ КОÐСТÐÐТ -----------------------------
11#------------------------------------------------------------------------------
12
13# текущий год и меÑÑц Ð´Ð»Ñ Ð¸Ð¼ÐµÐ½Ð¸ меÑÑчного бÑкапа
14MONTH = str(datetime.datetime.now().year) + "." + str(datetime.datetime.now().month).rjust(2,'0')
15
16# Ð¿Ð¾Ð»Ð½Ð°Ñ Ð´Ð°Ñ‚Ð° Ð´Ð»Ñ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ð¾Ð³Ð¾ бÑкапа
17FULL_DATE = MONTH + "." + str(datetime.datetime.now().day).rjust(2,'0')
18
19BASE_DIR = ""
20MONTH_DIR = ""
21DAILY_DIR = ""
22
23
24# Ð°Ð´Ñ€ÐµÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Ð´Ð»Ñ ÐµÐ¶ÐµÐ¼ÐµÑÑчного полного бÑкапа
25FULL_MONTH_DIR = BASE_DIR + MONTH_DIR
26
27# Ð°Ð´Ñ€ÐµÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Ð´Ð»Ñ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ð¾Ð³Ð¾ бÑкапа
28FULL_DAILY_DIR = BASE_DIR + DAILY_DIR
29
30# каталог текущего днÑ
31CURRENT_DAY_DIR = FULL_DAILY_DIR + MONTH + "/"
32
33# каталоги Ð´Ð»Ñ Ð±Ñкапа
34BACKUP_DIRS = []
35
36#------------------------------------------------------------------------------
37# ПроверÑет ÑущеÑтвует ли каталог ежемеÑÑчных бÑкапов
38# ДоÑтупна ли запиÑÑŒ в него
39def check_month_dir():
40 # ÑущеÑтвует ли каталог ежемеÑÑчных бÑкапов
41 if not os.path.exists(FULL_MONTH_DIR):
42 try:
43 os.system("chmod 0777 " + BASE_DIR)
44 os.system("mkdir " + FULL_MONTH_DIR)
45 except Exception, err:
46 print str(err)
47 # можем ли пиÑать в ежемеÑÑчные бÑкапы
48 if not os.access(FULL_MONTH_DIR, os.W_OK):
49 os.system("chmod 0777 " + FULL_MONTH_DIR)
50
51#------------------------------------------------------------------------------
52# Производит меÑÑчный бÑкап
53def backup_monthly():
54 os.system("tar cvfz " + FULL_MONTH_DIR + "backup." + MONTH + ".tar.gz -g " + FULL_MONTH_DIR + "backup." + MONTH + ".snar " + " ".join(BACKUP_DIRS))
55
56#------------------------------------------------------------------------------
57# ПроверÑет ÑущеÑтвует ли каталог ежедневных бÑкапов
58# ДоÑтупна ли запиÑÑŒ в него
59def check_daily_dir():
60 # ÑущеÑтвует ли каталог ежедневных бÑкапов
61 if not os.path.exists(FULL_DAILY_DIR):
62 try:
63 os.system("chmod 0777 " + BASE_DIR)
64 os.system("mkdir " + FULL_DAILY_DIR)
65 # ÑущеÑтвует ли
66 except Exception, err:
67 print str(err)
68
69 if not os.path.exists(CURRENT_DAY_DIR):
70 try:
71 os.system("chmod 0777 " + FULL_DAILY_DIR)
72 os.system("mkdir " + CURRENT_DAY_DIR)
73 except Exception, err:
74 print str(err)
75
76 if not os.access(FULL_DAILY_DIR, os.W_OK):
77 os.system("chmod 0777 " + FULL_DAILY_DIR)
78
79 if not os.access(CURRENT_DAY_DIR, os.W_OK):
80 os.system("chmod 0777 " + CURRENT_DAY_DIR)
81
82#------------------------------------------------------------------------------
83# Производит ежедневный бÑкап
84# ЕÑли полного бÑкапа за Ñтот меÑÑц не ÑущеÑтвует, то он ÑоздаётÑÑ
85def backup_daily():
86 if not os.path.exists(FULL_MONTH_DIR + "backup." + MONTH + ".tar.gz") and not os.path.isfile(FULL_MONTH_DIR + "backup." + MONTH + ".tar.gz"):
87 check_month_dir()
88 backup_monthly()
89 os.system("tar cvfz " + CURRENT_DAY_DIR + "backup." + FULL_DATE + ".tar.gz -g " + FULL_MONTH_DIR + "backup." + MONTH + ".snar " + " ".join(BACKUP_DIRS))
90
91#------------------------------------------------------------------------------
92# ВоÑÑтанавливаем данные
93def recover(recover_date):
94 if os.path.exists(BASE_DIR + DAILY_DIR + recover_date[:7] + "/"):
95 increments = os.listdir(BASE_DIR + DAILY_DIR + recover_date[:7] + "/")
96
97 if len(increments) > 0:
98 os.system("tar xvf " + FULL_MONTH_DIR + "backup." + recover_date[:7] + ".tar.gz --overwrite -g " + FULL_MONTH_DIR + "backup." + MONTH + ".snar ")
99 else:
100 print u"Ðет бÑкапов на указанный меÑÑц"
101 sys.exit(3)
102
103 for increment_file in increments:
104 print int(recover_date[8:]), '****', int(increment_file[15:17])
105 if int(recover_date[8:]) < int(increment_file[15:17]):
106 break
107 os.system("tar xvf " + BASE_DIR + DAILY_DIR + recover_date[:7] + "/" + increment_file + " --overwrite -g " + FULL_MONTH_DIR + "backup." + MONTH + ".snar ")
108 #print BASE_DIR + DAILY_DIR + recover_date[:7] + "/" + increment_file
109 if recover_date in increment_file:
110 break
111 else:
112 print u"Ðет бÑкапов на указанный меÑÑц"
113
114#------------------------------------------------------------------------------
115
116def main():
117 usage = u""" Скрипт Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ð¸ резервных копий.
118 Ðвтор: Мешин Дмитрий (aka doctor-demon), 0x7ffec at gmail.com
119
120 Делает ежемеÑÑчно полный бÑкап файловой ÑиÑтемы,
121 и каждый день делает инкрементный бÑкап
122 на оÑнове предыдущего инкрементного бÑкапа.
123 Таким образом, в каждом каталоге ежедневного бÑкапа
124 будет около 30 файлов ежедневных бÑкапов, что вполне
125 приемлемо в Ñлучае ручного воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¾Ð¹ ÑиÑтемы.
126
127 Удаление Ñтарых бÑкапов производитÑÑ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÑŽ на Ñтрах и риÑк.
128
129 Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ Ñправки: python %prog --help
130
131
132 Пример ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐµÐ¶ÐµÐ¼ÐµÑÑчного бÑкапа: python %prog --base-folder=/home/tux/backups --month-folder=/monthly --daily-folder=/daily --monthly -F /home/tux/pron:/etc/hosts:home/tux/.vimrc"""
133 parser = OptionParser(usage)
134 parser.enable_interspersed_args()
135 parser.add_option("-B", "--base-folder", dest="base_folder", help=u"Каталог Ð´Ð»Ñ Ð±Ñкапов")
136 parser.add_option("-M", "--month-folder", dest="month_folder", help=u"Подкаталог Ð´Ð»Ñ ÐµÐ¶ÐµÐ¼ÐµÑÑчных бÑкапов")
137 parser.add_option("-D", "--daily-folder", dest="daily_folder", help=u"Подкаталог Ð´Ð»Ñ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ñ‹Ñ… бÑкапов")
138 parser.add_option("-o", "--output", dest="filename", help=u"ЗапиÑывать отчёт в файл")
139 parser.add_option("-F", "--files", dest="files", help=u"СпиÑок файлов и каталогов Ð´Ð»Ñ Ð·Ð°Ð½ÐµÑÐµÐ½Ð¸Ñ Ð² бÑкап")
140 parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help=u"Подробный отчёт")
141 parser.add_option("-m", "--monthly", action="store_true", dest="monthly", help=u"ЕжемеÑÑчный бÑкап")
142 parser.add_option("-d", "--daily", action="store_true", dest="daily", help=u"Ежедневный бÑкап")
143 parser.add_option("-r", "--recover", action="store", type="string", dest="recovery_date", help=u"ВоÑÑтановить файлы из архива на чиÑло указанное в формате yyyy.mm.dd. Ðапример: python " + __file__ + u" -r 2010.02.05 - воÑÑтановит файловую ÑиÑтему на ÑоÑтоÑние, которое указано в дате")
144
145 (options, args) = parser.parse_args()
146
147 if options.base_folder:
148 global BASE_DIR
149 BASE_DIR = options.base_folder
150
151 if options.month_folder:
152 global MONTH_DIR
153 MONTH_DIR = options.month_folder
154
155 if options.daily_folder:
156 global DAILY_DIR
157 DAILY_DIR = options.daily_folder
158
159 # Ð°Ð´Ñ€ÐµÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Ð´Ð»Ñ ÐµÐ¶ÐµÐ¼ÐµÑÑчного полного бÑкапа
160 global FULL_MONTH_DIR
161 FULL_MONTH_DIR = BASE_DIR + MONTH_DIR
162
163 # Ð°Ð´Ñ€ÐµÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð° Ð´Ð»Ñ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ð¾Ð³Ð¾ бÑкапа
164 global FULL_DAILY_DIR
165 FULL_DAILY_DIR = BASE_DIR + DAILY_DIR
166
167 # каталог текущего днÑ
168 global CURRENT_DAY_DIR
169 global MONTH
170 CURRENT_DAY_DIR = FULL_DAILY_DIR + MONTH + "/"
171
172 if options.files:
173 global BACKUP_DIRS
174 BACKUP_DIRS = options.files.split(":")
175
176 if options.monthly:
177 check_month_dir()
178 backup_monthly()
179 return 0
180
181 if options.daily:
182 check_daily_dir()
183 backup_daily()
184 return 0
185
186 if options.recovery_date:
187 check_month_dir()
188 recover(options.recovery_date)
189
190if __name__ == "__main__":
191 main()