Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # Vietnix's script backup incremental vestacp
- import paramiko
- import os
- import time
- import shutil
- from datetime import datetime, timedelta
- REMOTE_IP = "125.212.xxx.xxx"
- REMOTE_PASSWORD = "xxxxxxxxxxxx"
- REMOTE_SOURCE_DIR = "/home"
- REMOTE_DB_DIR = "/root/backup-db" # folder store temp databases on remote server
- PASSWORD_MYSQL = "xxxxxxxxxx"
- LOCAL_BACKUP_DIR = "/home/backup-incremental"
- EXCLUDE_USER = ['backup', 'admin', 'backup-db']
- EXCLUDE_DB = ['Database', 'admin_default', 'information_schema', 'mysql', 'performance_schema', 'roundcube']
- ROTATE = 7 #days
- TODAY=time.strftime('%d-%m-%Y')
- YESTERDAY=datetime.strftime(datetime.today() - timedelta(1), '%d-%m-%Y')
- #################### Utility #########################
- # Function run command on remote server
- def run_command(command):
- client = paramiko.SSHClient()
- client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- client.connect(REMOTE_IP, username="root", password=REMOTE_PASSWORD)
- stdin, stdout, stderr = client.exec_command(command)
- exit_status = stdout.channel.recv_exit_status()
- if exit_status == 0:
- result = stdout.read().decode('ascii').splitlines()
- return result
- else:
- print(stderr.read())
- client.close()
- # Function create an transport with remote server
- def sftp_connect():
- # Open a transport
- transport = paramiko.Transport((REMOTE_IP, 22))
- # Authen
- transport.connect(username="root", password=REMOTE_PASSWORD)
- sftp = paramiko.SFTPClient.from_transport(transport)
- return sftp
- if sftp: sftp.close()
- if transport: transport.close()
- # Check & make folder on remote server
- def make_dir_on_remote(path):
- sftp = sftp_connect()
- print("[!] Create folder {} on remote server".format(path))
- try:
- sftp.chdir(path)
- except IOError:
- sftp.mkdir(path)
- sftp.chdir(path)
- # List file in remote
- def list_dir_remote(path):
- sftp = sftp_connect()
- return sftp.listdir(path)
- # Download on remote server
- def download_dir_remote(remote_path, local_path):
- sftp = sftp_connect()
- sftp.get(remote_path, local_path)
- # Delete on remote server
- def delete_dir_on_remote(path):
- sftp = sftp_connect()
- sftp.remove(path)
- # Upload on remote server
- def upload_dir_remote(path):
- sftp = sftp_connect()
- sftp.put(path)
- # List all user Vestacp need to backup
- def list_user(path):
- command = "ls {}".format(path)
- result = run_command(command)
- final = []
- for user in result:
- if user not in EXCLUDE_USER:
- final.append(user)
- return final
- # Check folder exist and create on local server
- def make_dir(path):
- if not os.path.exists(path):
- os.makedirs(path)
- ########################### MAIN #############################
- ######## Source backup #########
- def sync_backup(path, users):
- local_backup_source_dir = os.path.join(LOCAL_BACKUP_DIR, "source")
- make_dir(local_backup_source_dir)
- for user in users:
- backup_folder_today = os.path.join(local_backup_source_dir, user, TODAY)
- backup_folder_yesterday = os.path.join(local_backup_source_dir, user, YESTERDAY)
- web_dir = os.path.join(path, user , "web")
- make_dir(backup_folder_today)
- if not os.path.exists(backup_folder_yesterday):
- print("[!] Do not exist old backup, create new backup {}.".format(backup_folder_today))
- os.system('rsync -avz --delete root@{}:{} {}'.format(REMOTE_IP, web_dir, backup_folder_today))
- else:
- print("[!] Exist old backup, create incremental backup {}.".format(backup_folder_today))
- os.system('cp -al {} {}'.format(backup_folder_yesterday, backup_folder_today))
- os.system('rsync -avz --delete root@{}:{} {}'.format(REMOTE_IP, web_dir, backup_folder_today))
- # Rotate old backup
- def remove_old_backup_source(users):
- for user in users:
- backup_user_path = os.path.join(LOCAL_BACKUP_DIR, "source", user)
- list_backup = os.listdir(backup_user_path)
- full_path = ["{}/{}".format(backup_user_path, i) for i in list_backup]
- if ROTATE < len(list_backup):
- print("[!] The number of list backups in user {} is more than {}, delete oldest backup!".format(user, ROTATE))
- oldest_backup = min(full_path, key=os.path.getctime)
- print("[!] {} will be delete.".format(oldest_backup))
- shutil.rmtree(oldest_backup)
- else:
- print("[!] The number of list backups in user {} is less than {}, no delete backup!".format(user, ROTATE))
- ######## Database backup ##########
- # List all db need to backup on remote server
- def list_db_backup(password):
- command = 'mysql -uroot -p{} -e "show databases;" | grep -v "+---"'.format(password)
- list_full_db = run_command(command)
- final = []
- for db in list_full_db:
- if db not in EXCLUDE_DB:
- final.append(db)
- return final
- def dump_db(path, db_list):
- backup_db_dir_today = os.path.join(LOCAL_BACKUP_DIR, "db", TODAY)
- make_dir_on_remote(path)
- # list_old_db = list_dir_remote(path)
- # for db in list_old_db:
- # path_old_db = os.path.join(path, db)
- # print("[!] Delete old db {} on remote server".format(db))
- # delete_dir_on_remote(path_old_db)
- make_dir(backup_db_dir_today)
- for db in db_list:
- remote_db = os.path.join(path, "{}.sql".format(db))
- local_db = os.path.join(backup_db_dir_today, "{}.sql".format(db))
- print("[!] Dumping new db {}".format(db))
- command = "mysqldump {} > {}/{}.sql".format(db, path, db)
- run_command(command)
- print("[!] Downloading new db {}.sql".format(db))
- download_dir_remote(remote_db, local_db)
- def remove_old_backup_db(path):
- list_backup = os.listdir('{}/db'.format(path))
- full_path = [os.path.join(path, "db", i) for i in list_backup]
- print(full_path)
- if ROTATE < len(list_backup):
- print("[!] Number of database backup is greater {}, delete oldest backup".format(ROTATE))
- oldest_backup = min(full_path, key=os.path.getctime)
- print("[!] Backup {} will be delete".format(oldest_backup))
- shutil.rmtree(oldest_backup)
- else:
- print("[!] Number of database backup is less than {}, do not delete backup".format(ROTATE))
- '''
- Main function
- '''
- if __name__ == '__main__':
- users = list_user(REMOTE_SOURCE_DIR)
- sync_backup(REMOTE_SOURCE_DIR, users)
- remove_old_backup_source(users)
- db_list = list_db_backup(PASSWORD_MYSQL)
- dump_db(REMOTE_DB_DIR, db_list)
- remove_old_backup_db(LOCAL_BACKUP_DIR)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement