-
Notifications
You must be signed in to change notification settings - Fork 1
/
python-backups.py
126 lines (96 loc) · 2.86 KB
/
python-backups.py
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
__title__ = "python-backups"
__author__ = "Paulo Antunes"
__credits__ = [
"Paulo Antunes",
]
__license__ = "MIT"
__maintainer__ = "Paulo Antunes"
__email__ = "[email protected]"
__version__ = "0.1.0"
import logging
import os
import sys
import shutil
import schedule
import time
import subprocess
from shlex import split
from datetime import datetime
from environs import Env
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(message)s',
filename='/tmp/{}.log'.format(os.path.basename(__file__).split('.')[0]),
filemode='w'
)
env = Env()
env.read_env()
def _run_command(command, _id):
process = subprocess.Popen(
split(command),
stdout=subprocess.PIPE,
universal_newlines=True
)
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
logger.info('{} - {}'.format(_id, output.strip()))
rc = process.poll()
return rc
def _rsync(now):
for path in env.list('SOURCE_PATHS'):
project_name = path.split('/')[-2]
destination_path = os.path.join(
env('DESTINATION_PATH'),
now.strftime('%Y-%m-%d~%H%M'),
project_name
)
os.makedirs(destination_path)
_cmd = 'rsync -av -e "ssh -o Compression=no" {} {}'.format(
path, destination_path)
logger.info('COMMAND: {}'.format(_cmd))
_run_command(_cmd, _id=project_name)
def _clean_old_backups():
list_backups = sorted([x for x in os.listdir(env('DESTINATION_PATH'))])
to_remove = list_backups[:-env.int('NUMBER_OF_LAST_BACKUPS_KEPT')]
logger.info('REMOVE: {}'.format(to_remove))
for x in to_remove:
shutil.rmtree(os.path.join(env('DESTINATION_PATH'), x))
def job():
now = datetime.now()
try:
_rsync(now=now)
except subprocess.CalledProcessError as e:
logger.info('ERROR: '.format(e.output))
sys.exit(0)
_clean_old_backups()
logger.info(
'TIME: {:0.2f} minute(s)'.format(
(datetime.now() - now).total_seconds() / 60
)
)
if __name__ == "__main__":
if env('DEBUG', None):
logger.info('DEBUG=Yes')
job()
sys.exit(0)
pim = env.int('POOLING_INTERVAL_IN_MINUTES', None)
pt = env('POOLING_TIME', None)
if not (bool(pim) ^ bool(pt)):
logger.info('Only 1 POOLING config should be set')
sys.exit(0)
if pim:
logger.info('Scheduling Task to run each {} minutes'.format(pim))
schedule.every(pim).minutes.do(job)
elif pt:
logger.info('Scheduling Task at {}'.format(pt))
schedule.every().day.at(pt).do(job)
else:
logger.info('POOLING config not found')
sys.exit(0)
while True:
schedule.run_pending()
time.sleep(1)