Created
April 13, 2017 07:58
-
-
Save mmendozadelsolar/4bb8e707c042c1a68a7863434774deba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python | |
| #Author: Jelle Bekker | |
| #Base for this script was created by: Andrew McDonald [email protected] http://mcdee.com.au | |
| # Example: config file | |
| #[client] | |
| #host = localhost | |
| #user = root | |
| #password = root-pass | |
| #For parameter usage, use the -h parameter | |
| from datetime import datetime | |
| import argparse | |
| import os | |
| import subprocess | |
| import sys | |
| import tarfile | |
| import time | |
| def is_dir(path): | |
| """Checks if a path is an actual directory""" | |
| if not os.path.isdir(path): | |
| msg = "{0} is not a directory".format(path) | |
| raise argparse.ArgumentTypeError(msg) | |
| else: | |
| return path | |
| def is_file(path): | |
| """Checks if a path is a valid file""" | |
| if not os.path.isfile(path): | |
| msg = "{0} is not a valid file".format(path) | |
| raise argparse.ArgumentTypeError(msg) | |
| else: | |
| return path | |
| def get_args(): | |
| parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter) | |
| parser.add_argument('--cnf', action='store', type=is_file, required=True, help= | |
| ("Path to a config file with the following contents:\n" | |
| "\n" | |
| "[client]\n" | |
| "user = [root]\n" | |
| "password = [root-pass]\n" | |
| "host = [localhost]\n") | |
| ) | |
| parser.add_argument('--backup-directory', type=is_dir, required=True, help='Target directory for the backup') | |
| parser.add_argument('--compress', action='store_true', help='Compress the backup files') | |
| parser.add_argument('--age', type=int, help='Delete backup files older than the specified amount of days') | |
| return parser.parse_args() | |
| def set_permissions(path, permissions=0640): | |
| return os.chmod(path, permissions) | |
| def mysql_dblist(cnf): | |
| ignore_db = ['information_schema', 'performance_schema', 'test'] | |
| cmd = ['mysql', '--defaults-extra-file='+cnf, '-se', 'show databases'] | |
| p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| stdout, stderr = p.communicate() | |
| if p.returncode >0: | |
| print "MySQL Error:" | |
| print stderr | |
| sys.exit(1) | |
| dblist = stdout.strip().split('\n') | |
| for item in ignore_db: | |
| try: | |
| dblist.remove(item) | |
| except ValueError: | |
| continue | |
| if len(dblist) == 0: | |
| print "Doesn't appear to be any user databases found" | |
| return dblist | |
| def mysql_backup(dblist, cnf, dir, compress): | |
| for db in dblist: | |
| bdate = datetime.now().strftime('%Y%m%d%H%M') | |
| bfile = db+'_'+bdate+'.sql' | |
| fullpath = os.path.join(dir, bfile) | |
| dumpfile = open(fullpath, 'w') | |
| set_permissions(fullpath) | |
| if db == 'mysql': | |
| cmd = ['mysqldump', '--defaults-extra-file='+cnf, '--events', db] | |
| else: | |
| cmd = ['mysqldump', '--defaults-extra-file='+cnf, db] | |
| p = subprocess.Popen(cmd, stdout=dumpfile) | |
| retcode = p.wait() | |
| dumpfile.close() | |
| if retcode > 0: | |
| print 'Error:', db, 'backup error' | |
| if compress: | |
| backup_compress(fullpath, bfile) | |
| def backup_compress(path, bfile): | |
| try: | |
| tar = tarfile.open(path+'.tar.gz', 'w:gz') | |
| tar.add(path, arcname=bfile) | |
| tar.close() | |
| set_permissions(path+'.tar.gz') | |
| except Exception as e: | |
| print 'Error compressing {0} ({1}): {2}'.format(path, e.errno, e.strerror) | |
| os.remove(path) | |
| def cleanup_files(path, age): | |
| if age is not None: | |
| now = time.time() | |
| for bf in os.listdir(path): | |
| f = os.path.join(path, bf) | |
| if os.stat(f).st_mtime < now - age * 86400 and os.path.isfile(f): | |
| try: | |
| os.remove(f) | |
| except IOError as e: | |
| print "I/O error({0}): {1}".format(e.errno, e.strerror) | |
| def main(): | |
| args = get_args() | |
| db_list = mysql_dblist(args.cnf) | |
| mysql_backup(db_list, args.cnf, args.backup_directory, args.compress) | |
| cleanup_files(args.backup_directory, args.age) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment