SHARE
TWEET

Untitled

dungnguyen2 Feb 27th, 2020 128 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. # Vietnix's script backup incremental vestacp
  3.  
  4. import paramiko
  5. import os
  6. import time
  7. import shutil
  8. from datetime import datetime, timedelta
  9.  
  10. REMOTE_IP = "125.212.xxx.xxx"
  11. REMOTE_PASSWORD = "xxxxxxxxxxxx"
  12. REMOTE_SOURCE_DIR = "/home"
  13. REMOTE_DB_DIR = "/root/backup-db" # folder store temp databases on remote server
  14. PASSWORD_MYSQL = "xxxxxxxxxx"
  15. LOCAL_BACKUP_DIR = "/home/backup-incremental"
  16. EXCLUDE_USER = ['backup', 'admin', 'backup-db']
  17. EXCLUDE_DB = ['Database', 'admin_default', 'information_schema', 'mysql', 'performance_schema', 'roundcube']
  18. ROTATE = 7 #days
  19. TODAY=time.strftime('%d-%m-%Y')
  20. YESTERDAY=datetime.strftime(datetime.today() - timedelta(1), '%d-%m-%Y')
  21.  
  22.  
  23. #################### Utility #########################
  24. # Function run command on remote server
  25. def run_command(command):
  26.     client = paramiko.SSHClient()
  27.     client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  28.     client.connect(REMOTE_IP, username="root", password=REMOTE_PASSWORD)
  29.     stdin, stdout, stderr = client.exec_command(command)
  30.     exit_status = stdout.channel.recv_exit_status()
  31.        
  32.     if exit_status == 0:
  33.         result = stdout.read().decode('ascii').splitlines()
  34.         return result
  35.     else:
  36.         print(stderr.read())
  37.     client.close()
  38.  
  39. # Function create an transport with remote server
  40. def sftp_connect():
  41.     # Open a transport
  42.     transport = paramiko.Transport((REMOTE_IP, 22))
  43.     # Authen
  44.     transport.connect(username="root", password=REMOTE_PASSWORD)
  45.     sftp = paramiko.SFTPClient.from_transport(transport)
  46.     return sftp
  47.     if sftp: sftp.close()
  48.     if transport: transport.close()
  49.  
  50. # Check & make folder on remote server
  51. def make_dir_on_remote(path):
  52.     sftp = sftp_connect()
  53.     print("[!] Create folder {} on remote server".format(path))
  54.     try:
  55.         sftp.chdir(path)
  56.     except IOError:
  57.         sftp.mkdir(path)
  58.         sftp.chdir(path)
  59.  
  60. # List file in remote
  61. def list_dir_remote(path):
  62.     sftp = sftp_connect()
  63.     return sftp.listdir(path)
  64.  
  65. # Download on remote server
  66. def download_dir_remote(remote_path, local_path):
  67.     sftp = sftp_connect()
  68.     sftp.get(remote_path, local_path)
  69.  
  70. # Delete on remote server
  71. def delete_dir_on_remote(path):
  72.     sftp = sftp_connect()
  73.     sftp.remove(path)
  74.  
  75. # Upload on remote server
  76. def upload_dir_remote(path):
  77.     sftp = sftp_connect()
  78.     sftp.put(path)
  79.  
  80. # List all user Vestacp need to backup
  81. def list_user(path):
  82.     command = "ls {}".format(path)
  83.     result = run_command(command)
  84.     final = []
  85.     for user in result:
  86.         if user not in EXCLUDE_USER:
  87.             final.append(user)
  88.     return final
  89.  
  90. # Check folder exist and create on local server
  91. def make_dir(path):
  92.     if not os.path.exists(path):
  93.         os.makedirs(path)
  94.  
  95. ########################### MAIN #############################
  96.  
  97. ######## Source backup #########
  98. def sync_backup(path, users):
  99.     local_backup_source_dir = os.path.join(LOCAL_BACKUP_DIR, "source")
  100.     make_dir(local_backup_source_dir)
  101.  
  102.     for user in users:
  103.         backup_folder_today = os.path.join(local_backup_source_dir, user, TODAY)
  104.         backup_folder_yesterday = os.path.join(local_backup_source_dir, user, YESTERDAY)
  105.         web_dir = os.path.join(path, user , "web")
  106.         make_dir(backup_folder_today)
  107.         if not os.path.exists(backup_folder_yesterday):
  108.             print("[!] Do not exist old backup, create new backup {}.".format(backup_folder_today))
  109.             os.system('rsync -avz --delete root@{}:{} {}'.format(REMOTE_IP, web_dir, backup_folder_today))
  110.         else:
  111.             print("[!] Exist old backup, create incremental backup {}.".format(backup_folder_today))
  112.             os.system('cp -al {} {}'.format(backup_folder_yesterday, backup_folder_today))
  113.             os.system('rsync -avz --delete root@{}:{} {}'.format(REMOTE_IP, web_dir, backup_folder_today))
  114.  
  115. # Rotate old backup        
  116. def remove_old_backup_source(users):
  117.     for user in users:
  118.         backup_user_path = os.path.join(LOCAL_BACKUP_DIR, "source", user)
  119.         list_backup = os.listdir(backup_user_path)
  120.         full_path = ["{}/{}".format(backup_user_path, i) for i in list_backup]
  121.  
  122.         if ROTATE < len(list_backup):
  123.             print("[!] The number of list backups in user {} is more than {}, delete oldest backup!".format(user, ROTATE))
  124.             oldest_backup = min(full_path, key=os.path.getctime)
  125.             print("[!] {} will be delete.".format(oldest_backup))
  126.             shutil.rmtree(oldest_backup)
  127.         else:
  128.             print("[!] The number of list backups in user {} is less than {}, no delete backup!".format(user, ROTATE))
  129.  
  130.  
  131. ######## Database backup ##########
  132. # List all db need to backup on remote server
  133. def list_db_backup(password):
  134.     command = 'mysql -uroot -p{} -e "show databases;" | grep -v "+---"'.format(password)
  135.     list_full_db = run_command(command)
  136.     final = []
  137.     for db in list_full_db:
  138.         if db not in EXCLUDE_DB:
  139.             final.append(db)
  140.     return final
  141.  
  142. def dump_db(path, db_list):
  143.     backup_db_dir_today = os.path.join(LOCAL_BACKUP_DIR, "db", TODAY)
  144.     make_dir_on_remote(path)
  145. #    list_old_db = list_dir_remote(path)
  146. #    for db in list_old_db:
  147. #        path_old_db = os.path.join(path, db)
  148. #        print("[!] Delete old db {} on remote server".format(db))
  149. #        delete_dir_on_remote(path_old_db)
  150.     make_dir(backup_db_dir_today)
  151.     for db in db_list:
  152.         remote_db = os.path.join(path, "{}.sql".format(db))
  153.         local_db = os.path.join(backup_db_dir_today, "{}.sql".format(db))
  154.         print("[!] Dumping new db {}".format(db))
  155.         command = "mysqldump {} > {}/{}.sql".format(db, path, db)
  156.         run_command(command)
  157.         print("[!] Downloading new db {}.sql".format(db))
  158.         download_dir_remote(remote_db, local_db)
  159.  
  160. def remove_old_backup_db(path):
  161.     list_backup = os.listdir('{}/db'.format(path))
  162.     full_path = [os.path.join(path, "db", i) for i in list_backup]
  163.     print(full_path)
  164.     if ROTATE < len(list_backup):
  165.         print("[!] Number of database backup is greater {}, delete oldest backup".format(ROTATE))
  166.         oldest_backup = min(full_path, key=os.path.getctime)
  167.         print("[!] Backup {} will be delete".format(oldest_backup))
  168.         shutil.rmtree(oldest_backup)
  169.     else:
  170.         print("[!] Number of database backup is less than {}, do not delete backup".format(ROTATE))
  171.  
  172.  
  173. '''
  174. Main function
  175. '''
  176. if __name__ == '__main__':
  177.     users = list_user(REMOTE_SOURCE_DIR)
  178.     sync_backup(REMOTE_SOURCE_DIR, users)
  179.     remove_old_backup_source(users)
  180.     db_list = list_db_backup(PASSWORD_MYSQL)
  181.     dump_db(REMOTE_DB_DIR, db_list)
  182.     remove_old_backup_db(LOCAL_BACKUP_DIR)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top