#!/usr/bin/python3 # mongodb backup script # Copyright (C) 2021 Philipp Fromme # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import ast import datetime, time import os, sys, pwd import string import subprocess import configparser config_file = '/etc/mongodb_backup.conf' config = configparser.ConfigParser() if os.path.exists(config_file): config.read(config_file) # Set variables from config file if available, otherwise default mdb_conf = config['mongodb-backup'] BAKDIR = mdb_conf.get('BAKDIR', '/var/mongodb_bak') MAXAGE = mdb_conf.getint('MAXAGE', 1) MONGODB_OPT = mdb_conf.get('MONGODB_OPT') CLEANUPBEFORE = mdb_conf.getboolean('CLEANUPBEFORE', False) USERNAME = mdb_conf.get('USERNAME') PASSWORD = mdb_conf.get('PASSWORD') QUIET = mdb_conf.getboolean('QUIET', True) DB_IGNORE = dict(config.items('db_ignore')) DB_IGNORE_LIST = [] for key, db in DB_IGNORE.items(): DB_IGNORE_LIST.append(db) CURDIR = str(datetime.date.today()) def backup(databases): dest_dir = os.path.join(BAKDIR, CURDIR) mongodump_cmd = ['/usr/bin/mongodump', '--out', dest_dir] if MONGODB_OPT: mongodump_cmd += [MONGODB_OPT] if QUIET: mongodump_cmd += ['--quiet'] if USERNAME: mongodump_cmd += ['--username=' + USERNAME] if PASSWORD: mongodump_cmd += ['--password=' + PASSWORD] for db in databases: if db not in DB_IGNORE_LIST: db_arg = '--db=' + db mongodump_cmd += [db_arg] subprocess.run(mongodump_cmd) def cleanup(): if not QUIET: print('Cleaning up backup directory.') for directory in os.listdir(BAKDIR): if os.path.isdir(directory) and not directory == 'current': if os.path.getmtime(directory) < time.time() - (MAXAGE * 24 * 3600): # if backup is older than MAXAGE. delete it. dirpath = os.path.join(BAKDIR, directory) for root, dirs, files in os.walk(dirpath, topdown=False): for f in files: rm_file = os.path.join(root, f) if not QUIET: print('removing file %s' % rm_file) os.remove(rm_file) for d in dirs: rm_dir = os.path.join(root, d) if not QUIET: print('removing directory %s' % rm_dir) os.rmdir(rm_dir) if not QUIET: print('removing directory %s' % dirpath) os.rmdir(dirpath) else: if not QUIET: print('skip directory %s' % directory) if os.path.islink('current'): os.remove('current') os.symlink(CURDIR, 'current') def main(): # get databases get_db_cmd = ['mongo', '--quiet', '--eval', 'db.getMongo().getDBNames()'] if USERNAME: get_db_cmd += ['--username=' + USERNAME] if PASSWORD: get_db_cmd += ['--password=' + PASSWORD] get_db_output = subprocess.check_output(get_db_cmd) db_list = ast.literal_eval(get_db_output.decode().strip()) if not os.path.exists(BAKDIR): os.makedirs(BAKDIR) os.chmod(BAKDIR, mode=0o700) os.umask(0o177) os.chdir(BAKDIR) if not QUIET: print('Backup directory is %s' % (os.path.join(BAKDIR, CURDIR))) if CLEANUPBEFORE: cleanup() if not os.path.exists(CURDIR): os.mkdir(CURDIR) elif not QUIET: print('Folder already exists. Overwriting old backup from same day') if CLEANUPBEFORE: backup(db_list) else: backup(db_list) cleanup() if __name__ == '__main__': main()