I have several places to grab backups from and one place to store them – I don’t use mainstream cloud services (maybe I should…?), instead I store those onto my external drive.
Some of those places include web hosts, so I made this python script to grab ready-made backup archives and mirror some of the sites for me.
I wrote about my backup process on my blog
here.
And here's a script I made for this:
#!/usr/local/bin/python
'''
Date: 2015.08.02
Author: Kulverstukas
Website: 9v.lt; evilzone.org
Description:
Downloads backup files from /backups in set hosts
and downloads whole website content from defined website.
'''
import os
import sys
import time
import shutil
import zipfile
import ftputil
from ftplib import FTP
#-------------------------------------------------------
# where to put everything
rootFolder = 'webhost_backups'
# configuration of as many webshosts as you have
webhosts = [
{'folder' : 'somesite.lt', # where to store your files
'address' : 'somesite.lt', # URL of your website
'username' : 'lorem', # FTP username
'password' : 'ipsum', # FTP password
'backup_path' : '/backups', # usually this is where backups are stored on the server
'mirror' : True}, # should mirror the whole website starting from root
{'folder' : 'subdomain.domain.com',
'address' : 'subdomain.domain.com',
'username' : 'lorem',
'password' : 'ipsum',
'backup_path' : '/backups',
'mirror' : False}
]
#-------------------------------------------------------
# create folders if they don't exist already
if not os.path.exists(rootFolder) or not os.path.isdir(rootFolder):
os.mkdir(rootFolder)
#-------------------------------------------------------
# replace symbols with encoded equivalents
def makeFriendlyFilename(input):
badSymbols = {'<' : '%3C',
'>' : '%3E',
':' : '%3A',
'"' : '%22',
'|' : '%7C',
'?' : '%3F',
'*' : '%2A'}
i = ''
for i in badSymbols.keys():
input = input.replace(i, badSymbols[i]);
return input
#-------------------------------------------------------
def zipdir(path, zipname):
zipf = zipfile.ZipFile(zipname, 'w')
for root, dirs, files in os.walk(path):
for dir in dirs:
zipf.write(os.path.join(root, dir))
for file in files:
zipf.write(os.path.join(root, file))
zipf.close()
#-------------------------------------------------------
# download all of the files from FTP
def mirrorFtp():
for config in webhosts:
if config['mirror']:
today = time.strftime("%Y-%m-%d")
mirrorName = config['folder']+'_mirror_'+today
localMirrorRoot = os.path.join(rootFolder, config['folder'], mirrorName)
if not os.path.exists(localMirrorRoot) or not os.path.isdir(localMirrorRoot):
os.makedirs(localMirrorRoot)
ftp = ftputil.FTPHost(config['address'], config['username'], config['password'])
for root, dirs, files in ftp.walk('/'):
for dir in dirs:
try:
os.mkdir(os.path.join(localMirrorRoot, root[1:], dir))
except:
pass
for file in files:
try:
ftp.download(root+'/'+file, os.path.join(localMirrorRoot, root[1:], makeFriendlyFilename(file)))
except:
print root+'/'+file
zipdir(localMirrorRoot, localMirrorRoot+'.zip')
shutil.rmtree(localMirrorRoot)
#-------------------------------------------------------
# download backup files made by DirectAdmin
def getBackupFiles():
ftp = FTP()
for config in webhosts:
if not os.path.exists(rootFolder+'/'+config['folder']) or not os.path.isdir(rootFolder+'/'+config['folder']):
os.mkdir(rootFolder+'/'+config['folder'])
try:
ftp.connect(config['address'])
ftp.login(config['username'], config['password'])
ftp.cwd(config['backup_path'])
filesToDl = ftp.nlst();
for file in filesToDl:
if (file not in ['.', '..']):
ftp.retrbinary('RETR '+file, open(rootFolder+'/'+config['folder']+'/'+file, 'wb').write)
try:
# comment this out if you want to keep backup archives on the server
ftp.delete(file)
except:
pass
ftp.quit()
except:
pass
#-------------------------------------------------------
getBackupFiles()
mirrorFtp()
#-------------------------------------------------------