Autor Topic: Backup remoto con Source  (Visto 190 veces)

0 Miembros and 1 Guest are viewing this topic.

Offline Dante on: May 12, 2018, 10:37:01 PM

  • *
  • Rank: Principiante
  • Posts: 4
  • Gracias recibida: 9
Buenos dias a todos, por necesidades que me surgieron tuve que hacer un script que me permitiera realizar una copia de seguridad (backup) desde una computadora remota al equipo que contenia la informacion que era relevante para mi. Ya que lo hice (usando un codigo base) queria compartir el resultado con ustedes, tambien lo comente (no tan claro y conciso como me gustaria, lo admito) para que se entienda lo mejor posible:

Code: [Select]
#este programa se ha hecho teniendo en cuenta que se ejecutara
#de forma remota, es decir, no se ejecutara en el equipo local
#donde se encuentran los archivos que nos interesan respaldar,
#sino en un equipo remoto donde nos interesa que se almacene
#una copia de los mismos
 
#colores para la consola
class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    BOLD = "\033[1m"
    ENDC = '\033[0m'
 
 
    def disable(self):
        self.HEADER = ''
        self.OKBLUE = ''
        self.OKGREEN = ''
        self.WARNING = ''
        self.FAIL = ''
        self.ENDC = ''
 
 
#datos del equipo donde se encuentran los directorios a los cuales
#se les hara un respaldo
print(bcolors.BOLD + bcolors.WARNING + "NOTA: Se define equipo backup como el equipo en el cual se encuentran los archivos que buscamos respaldar" + bcolors.ENDC)
RemoteUser = input("nombre de usuario del equipo backup: ")
RemoteHost = input("IP de equipo backup: ")
 
#En Syncs se debe colocar una lista de los directorios a copiar
#en el equipo remoto, el formato debe ser '/ubicacion/directorio/'
Syncs = ['/Users/test/pythonBackups/carpeta1/','/Users/test/pythonBackups/imagen.jpeg','/Users/test/pythonBackups/carpeta2/texto2.txt']
 
# directorio donde guardaremos el backup localmente
TARGET_DIRECTORY = "/home/dante/programacion/testBackup/"
 
#Configuracion sobre si realizaremos un logfile o no
WRITE_LOGFILE = True # escribe un logfile en TARGET_DIRECTORY
 
#funcion llamada posteriormente para saber si debe realizarse un backup completo
def ask_ok(prompt, retries=4, complaint='y/n ?...'):
    while True:
        ok = input(prompt)
        if ok in ('y', 'Y', 'yes', 'Yes'):
            return True
        if ok in ('n', 'N', 'no', 'No'):
            return False
        print(complaint)
 
#funcion para log
def print2log(s, filehandle=0):
    global WRITE_LOGFILE
    sys.stdout.buffer.write(bytes(s, "utf-8"))
    sys.stdout.flush() 
    if (WRITE_LOGFILE==True) and filehandle and (s.find('\r')==-1):
        filehandle.write(bytes(s, "utf-8"))
 
 
#codigo "principal"
 
import time
import subprocess
import os
import sys
import re
 
# chequea si existe el directorio donde almacenaremos el backup
if not os.path.exists(TARGET_DIRECTORY):
    print("\nERROR: El directorio seleccionado \n>> "+TARGET_DIRECTORY+" <<\nno se encuentra disponible.")
    sys.exit()
 
# prepara logfile
if WRITE_LOGFILE:
    logFile = open(os.path.join(TARGET_DIRECTORY, 'rsync_' + time.strftime( "%Y-%m-%dT%H:%M:%S") + '.log'), 'wb')
else:
    logFile = 0
 
numBackupItems = len(Syncs) # cantidad de archivos / directorios a copiar
currBackupItem = 0
 
# realiza iteraciones sobre los directorios para ir haciendo los backups
for backupDir in Syncs:
   
    currBackupItem = currBackupItem + 1
   
    countStr = "("+str(currBackupItem)+"/"+str(numBackupItems)+")"
   
    print2log("\n-----------------------------------------------------------\n", logFile)
    print2log("Realizando backup de " + backupDir + " " + countStr +"\n", logFile)
    print2log("-----------------------------------------------------------\n", logFile)
   
 
    timestamp = time.strftime( "%Y-%m-%dT%H:%M:%S")
    current_backup_target = os.path.join(TARGET_DIRECTORY, os.path.basename(os.path.normpath(backupDir)))
    previous_backup_link = ""
 
    # Revisa si existen backups previos
    prevBackupsFound = False
    if os.path.exists(current_backup_target):
        dirListing = os.listdir(current_backup_target)
        dirListing = [name for name in os.listdir(current_backup_target) if os.path.isdir(os.path.join(current_backup_target,name))]
        # al hacer backup les damos a los nuevos directorios donde organizamos el contenido el formato de por ejemplo: 2013-06-24T18:44:31
        rex = re.compile('[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8}$')
        dirListing = [x for x in dirListing if rex.match(x)]
        numOldBackups = len(dirListing)
        if numOldBackups>0: #revisa si ya se hicieron backups antes
            dirListing.sort()
            dirListing.reverse()
            previous_backup_link = os.path.join(current_backup_target, dirListing[0])
            print2log("el backup anterior sera utilizado como hard link: "+previous_backup_link+"\n", logFile)
            previous_backup_link = '--link-dest="' + previous_backup_link +'" '
            prevBackupsFound = True
   
    # Si no encuentra viejos backups, pregunta si debe crear uno
    if not prevBackupsFound:
        print2log(bcolors.WARNING + bcolors.BOLD + "WARNING: No fue encontrado un backup previo.\n" + bcolors.ENDC, logFile)
        if ask_ok("Debemos realizar un backup completo ahora? (y/n)"):
            if not os.path.exists(current_backup_target):
                os.mkdir(current_backup_target)
        else:
            # si ask_ok retorna false, sigue con el siguiente item de la lista directory list
            continue     
    # usamos rsync, a es modo archivo, nos permite  copiar archivos de forma recursiva y conserva symbolic links
    rsynccmd = 'rsync -aP ' + previous_backup_link + ' --progress --stats '+ RemoteUser + '@'+ RemoteHost + ':' +backupDir + ' ' + os.path.join(current_backup_target,timestamp+"_tmp")
    #rsynccmd  = 'rsync -aP ' + previous_backup_link + ' ' + backupDir + ' ' + os.path.join(current_backup_target,timestamp+"_tmp")
    print2log("+" + countStr + "+ " + rsynccmd + "\n\n", logFile)
    rsyncproc = subprocess.Popen(rsynccmd,
                                       shell=True,
                                       stdin=subprocess.PIPE,
                                       stdout=subprocess.PIPE,
    )
 
    # lee el output de rsync y lo muestra en consola
    while True:
        next_line = rsyncproc.stdout.readline().decode("utf-8")
        if not next_line:
            break
        print2log("+" + countStr + "+ " + next_line, logFile)
 
    # Espera hasta que el proceso este terminado
    exitcode = rsyncproc.wait()
    # Chequea codigo de salida
    if exitcode==0:
        filename, file_extension = os.path.splitext(current_backup_target)
        if os.path.isfile(os.path.join(current_backup_target,timestamp+"_tmp")):
            os.rename(os.path.join(current_backup_target,timestamp+"_tmp"), os.path.join(current_backup_target,timestamp+file_extension))
        else:
            os.rename(os.path.join(current_backup_target,timestamp+"_tmp"), os.path.join(current_backup_target,timestamp))
            print2log(bcolors.OKGREEN + bcolors.BOLD + "Backup realizado con exito \n\n" + bcolors.ENDC, logFile)
    else:
        print2log(bcolors.FAIL + bcolors.BOLD + "\nFAIL: Parece que ocurrio un error :( \n\n" + bcolors.ENDC, logFile)
        break
 
# cierra log   
if (WRITE_LOGFILE==True) and logFile:
    logFile.close()



Para que el código funcione correctamente se requiere realizar las siguientes tareas antes de su ejecución:
-Se debe tener instalado python3 y rsync
-Modificar la variable Syncs en la cual se encuentra el listado de los directorios a los cuales se les hará un respaldo de datos. Debe colocarse la lista de carpetas que se desea copiar desde el equipo backup. Para ello debe seguirse la sintaxis indicada en los comentarios dentro del código fuente.
-Modificar la variable TARGET DIRECTORY, en la misma se debe colocar la dirección del directorio en la cual nosotros almacenaremos la copia de datos realizada de forma remota.

**Es aconsejable (pero no obligatorio) crear una clave pública y compartirla entre el equipo remoto y local de los cuales se disponen para realizar el backup de datos. Esto es para evitar el engorroso proceso de colocar la password del equipo por cada archivo copiado por rsync.

Las claves públicas se pueden hacer ejecutando el siguiente comando:

ssh-keygen

Se nos pedirá una frase, se puede dejar vacía.

Una vez generadas las keys procedemos a copiarla en la otra computadora:

ssh-copy-id -i ~/.ssh/id_rsa.pub usuario@server

Una vez realizado dicho procedimiento ya estaremos habilitados para acceder al otro servidor sin requerir una clave escrita.

Por último, es esencial verificar que el SSH se encuentra instalado y activo ya que de lo contrario obtendremos errores al momento de establecer la conexión.

El presente software puede:
-Realizar un backup completo de un conjunto de directorios desde una computadora remota
-Guardar un registro (logs) de todo lo realizado por el software
-almacenar las copias de cada directorio según un formato de anio-mes-dia:hora-minuto-segundo
-Si se realizan varias copias de un mismo archivo no se borran las versiones anteriores para dejar las ultimas, sino que se guardan todas las versiones y se las clasifica por fechas.

Solo sirve para computadoras con sistema opeartivo base linux (lo cual incluye MAC OSX)

« Ultima edicion: May 13, 2018, 12:35:05 AM by ZabiinoOo »

Gracias:


 

Related Topics

  Subject / Started by Replies Last post
5 Replies
707 Views
Last post November 12, 2016, 03:28:20 PM
by Alemarfar
11 Replies
1443 Views
Last post June 10, 2017, 08:29:04 PM
by melo920
5 Replies
325 Views
Last post September 20, 2017, 10:50:02 PM
by pepeeh
0 Replies
203 Views
Last post November 02, 2017, 11:47:53 PM
by seedmaker
1 Replies
211 Views
Last post December 04, 2017, 12:56:09 PM
by akuamen78