backups con python

C贸mo realizar backups con Python

Aunque existen potentes y sofisticadas herramientas para la realizaci贸n de copias de seguridad dentro de una organizaci贸n, 茅stas suelen ser sobredimensionadas para algunas tareas sencillas de este 谩mbito. Esas peque帽as actividades podemos suplirlas perfectamente con algunas l铆neas de c贸digo de programaci贸n. Por eso, en este art铆culo te explico varias formas de realizar backups con Python, para servidores.

Vamos a revisar cuatro archivos ejecutables de Python, cada uno con un c贸digo diferente para que conozcamos la diversidad de m茅todos para realizar copias de respaldo, desde el m谩s sencillo hasta el m谩s elaborado.

Primer script para realizar backups con Python


El primer c贸digo que vamos a ver para estos de los backups es muy sencillo. El siguiente archivo se llama script_1.py:

 

#!/usr/bin/env python3.8

import os

os.system('tar cvfz paginaweb-`date +%Y-%m-%d`.tar.gz /var/www/paginaweb')
os.system('cp pagnaweb-`date +%Y-%m-%d`.tar.gz /media/BACKUPS/Comprimidos/')
os.system('rm -rf paginaweb-`date +%Y-%m-%d`.tar.gz')

Nada trascendental. Se trata de comprimir una carpeta llamada paginaweb, incrust谩ndole en su nombre la fecha actual, luego se copia a otra carpeta (/media/BACKUPS/Comprimidos), y finalmente se borra.

Lo que sucede aqu铆 realmente es que estamos haciendo la copia de respaldo con los mismo comandos del sistema operativo. Hacemos eso llamadando el m茅todo os.system() de Python.

Segundo script para realizar backups con Python


Volvamos esto un poco m谩s interesante. En el siguiente script ya comenzamos a usar c贸digo propiamente de Python para realizar los backups.

Siempre que necesitemos hacer copias, o cualquier otro procesamiento sobre los archivos de una carpeta, debemos tratarlos como objetos de una lista. Por eso debemos generar la lista de archivos y luego procesarlos con el bucle for.

El siguiente script, llamado script_2.py, consiste en copiar los archivos de configuraci贸n de un servidor a una carpeta, luego se le comprime y finalemente se copia el comprimido a otra carpeta:

#!/usr/bin/env python3.8

import os, shutil, glob

#DEFINIMOS LOS ARCHIVOS Y CARPETAS QUE SE DEBEN COPIAR
ScriptsBashHome = '/home/sistemas/'
ScriptsBashInit = '/etc/init.d/'
ArchivosLogs = '/home/sistemas/'
ConfSquid = '/etc/squid/squid.conf'
ConfVPN = '/etc/openvpn/'
ConfShaper = '/etc/shaper/'
ConfDHCP = '/usr/local/etc/dhcpd.conf'

#DEFINIMOS LAS CARPETAS A DONDE PONDREMOS ESAS COPIAS
DestinoHome = '/home/sistemas/backup_proxy/sistemas'
DestinoBashInit = '/home/sistemas/backup_proxy/init'
DestinoSquid = '/home/sistemas/backup_proxy/squid'
DestinoShaper = '/home/sistemas/backup_proxy/shaper'
DestinoDHCP = '/home/sistemas/backup_proxy/dhcp'

DirectorioActual = '/home/sistemas'

DirectorioDestinoComprimidos = '/media/BACKUPS'

#COPIAMOS LOS SCRIPTS DE LA CARPETA SISTEMAS
for archivo in glob.glob(f'{ScriptsBashHome}/*.sh'):
    print('COPIANDO EL ARCHVIO: '+str(archivo))
    shutil.copy(archivo, DestinoHome)

#COPIAMOS LOS SCRIPTS DE LA CARPETA INIT.D
for archivo2 in glob.glob(f'{ScriptsBashInit}/*.sh'):
    print('COPIANDO EL ARCHIVO: '+str(archivo2))
    shutil.copy(archivo2, DestinoBashInit)

#COPIAMOS LOS LOGS EN FORMATO TXT (van en el mismo directorio Sistemas)
for archivo3 in glob.glob(f'{ArchivosLogs}/*.txt'):
    print('COPIANDO EL ARCHIVO: '+str(archivo3))
    shutil.copy(archivo3, DestinoHome)

#COPIAMOS EL ARCHIVO DE CONFIGURACI脫N DE SQUID
shutil.copy(ConfSquid, DestinoSquid)

#COPIAMOS EL DIRECTORIO COMPLETO DE OPENVPN
os.system('cp -r /etc/openvpn/ /home/sistemas/backup_proxy/vpn/')

#COPIAMOS LOS ARCHIVOS DE SHAPER
for archivo4 in glob.glob(f'{ConfShaper}/*.htt'):
    print('COPIANDO EL ARCHIVO: '+str(archivo4))
    shutil.copy(archivo4, DestinoShaper)

#COPIAMOS EL ARCHIVO DE CONFIGURACI脫N DE DHCP SERVER
shutil.copy(ConfDHCP, DestinoDHCP)

#GENERAMOS EL COMPRIMIDO Y LO COPIAMOS EN EL SERVIDOR 192.168.0.9
os.system('tar cvfz backup_proxy-`date +%Y-%m-%d`.tar.gz backup_proxy/')

for comprimido in glob.glob(f'{DirectorioActual}/*.gz'):
    print('SE GENER脫 EL SIGUIENTE COMPRIMIDO: '+str(comprimido))
    shutil.copy(comprimido, DirectorioDestinoComprimidos)
    os.remove(comprimido)

print('FUE UN PLACER, BYE')

 

Puedes ver que el script usa el m贸dulo Glob para buscar dentro del directorio que le pasamos par谩metro, todos los archivos que tengan cierto patr贸n, en nuestro caso archivos finalizados en .sh, .txt y .htt. Tambi茅n notar谩s que para cada uno de esas extensiones tenemos un bucle for.

Solo hay una excepci贸n: los archivos de configuraci贸n de OpenVpn. Eso se debe a que las llaves y certificados de los clientes de OpenVpn solo puede ser copiados por el usuario root. Aunque ejecutemos a script_2.py como root, ser谩 infructuosa la copia de OpenVpn.

As铆 las cosas, solo nos queda copiar los archivos de OpenVpn con los comandos propios de Linux por medio del m茅todo os.system(), que ya vimos en el script_1.py. Sin embargo, eso no es suficiente, porque como ya dije, solo root puede copiar esos archivos, y el script en ning煤n momento se loguea como root. Una alternativa sencilla, aunque algo peligrosa, es activar el bit SUID al comando cp y tar. De esa forma podemos copiar y comprimir los archivos de OpenVpn desde cualquier usuario (Ah铆 radica el peligro, pero suponemos que este servidor solo lo Administra una persona).

Finalmente comprimimos la carpeta backup_proxy, y de nuevo con el m贸dulo Glob, ubicamos ese comprimido y lo copiamos en el directorio destino. Aunque el m贸dulo Glob en este 煤ltima parte no es estrictamente necesario, porque solo vamos a copiar un solo archivo .gz (ser铆a suficiente con saber el nombre del comprimido y copiarlo con el m茅todo shutilcopy()). En el siguiente script vamos a copiar un comprimido por su nombre, y no con el m贸dulo Glob.

Ojo! Las carpetas destino deben estar creadas previamente, sino el script no funcionar谩. Una forma de solventar dicha situaci贸n es que el script valide la existencia de dichas carpetas, de lo contrario que proceda a crearlas.

Tercer script para realizar backups con Python


Bueno, para desenredarnos un poco de tanto c贸digo, vamos a revisar el siguiente script de backups, que tiene menos complejidad. En esta ocasi贸n vamos a comprimir un archivo de base de datos tipo MySQL, usando el c贸digo propio de Python:

#!/usr/bin/env python3.8

import os, shutil, tarfile, datetime

#HACEMOS UN VOLCADO DE TODAS LAS BASES DE DATOS DE MySQL
os.system('mysqldump --user=root --password=mi_contrase帽a -A > TODAS_LAS_BASESDEDATOS.sql')

#CONTRUIMOS EL NOMBRE QUE LE VAMOS A PONER AL COMPRIMIDO
FechaHoy= datetime.date.today()
TarBall = 'TODAS_LAS_BD-'
Extension = '.tar.gz'

comprimido = TarBall+str(FechaHoy)+Extension

#DEFINIMOS EL NOMBRE DEL ARCHIVO QUE VAMOS A COMPRIMIR
ArchivoSQL = 'TODAS_LAS_BASESDEDATOS.sql'

DirectorioDestino = '/opt/backups/Comprimidos/SIMPROV'

#COMPRIMIMOS EL ARCHIVO SQL Y LE PONEMOS EL NOMBRE QUE ARMAMOS EN LA VARIABLE comprimidos
tar = tarfile.open(comprimido, "w:gz")
tar.add(os.path.basename(ArchivoSQL)) #para copiar archivos
#tar.add("pruebas", arcname="comprimido") #para copiar directorios (directorio 'pruebas')
tar.close()

shutil.copy(comprimido, DirectorioDestino)
os.remove(comprimido)
os.remove('TODAS_LAS_BASESDEDATOS.sql')

 

Lo interesante del tercer script es la construcci贸n del nombre del comprimdo, porque necesitamos saber de qu茅 fechas son cada uno de esos backups. Ya sabiendo su nombre es m谩s f谩cil copiarlo en otro directorio, sin necesidad de hacer bucles.

Cuarto script


Volvamos a la complejidad. La funci贸n del siguiente script es hacer un recorrido por todas las subcarpetas de una principal, y si encuentra archivos cuya fecha de modificaci贸n es la de hoy, los copiara, con su respectivo subdirectorio y todo, en la carpeta destino

#!/usr/bin/env python3.8

import os, datetime, pathlib, shutil, glob

registro = open(‘bitacora.txt’, ‘a’)

#DEFINIMOS EL DIRECTORIO ORIGEN Y DESTINO
directorio_origen = pathlib.Path(‘pruebas/‘)
d_destino = ‘pruebas2/

#VERIFICAMOS QUE LA CARPETA ESTE ACCESIBLE
if os.path.isdir(directorio_origen) == True:
聽聽聽 print(‘EL DIRECTORIO EST脕 ACCESIBLE’)

聽聽聽 fecha_backup = datetime.date.today()

#VAMOS EN BUSCA DE SUBCARPETAS
聽聽聽 for subdirectorio in glob.glob(f'{directorio_origen}/**/’, recursive=True):

聽聽聽聽聽聽聽 #ITERAMOS POR CADA SUBCARPETA EN BUSCA DE ARCHIVOS
聽聽聽聽聽聽聽 for archivo in pathlib.Path(subdirectorio).iterdir():
聽聽聽聽聽聽聽聽聽聽聽 if os.path.isfile(archivo) == True:
聽聽聽聽聽聽聽聽聽聽聽 #OBTENEMOS LA FECHA DE MODIFICACION DEL ARCHIVO ITERADO
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 fecha_creacion = datetime.date.fromtimestamp(os.path.getmtime(archivo))
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 print(str(archivo)+’ ‘+str(fecha_creacion))

#SI EL ARCHIVO HA SIDO CREADO HOY, ENTONCES PROCEDEMOS A COPIARLO EN EL DIRECTORIO DESTINO
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 if fecha_creacion == datetime.date.today():
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 sub_directorio_destino = d_destino+subdirectorio
#SI EL SUBDIRECTORIO DESTINO NO EXISTE, LO CREAMOS Y PROCEDEMOS CON LA COPIA DEL ARCHIVO ENCONTRADO
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 if os.path.isdir(sub_directorio_destino) == False:
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 print(‘CREANDO DIRECTORIO NUEVO ‘+str(sub_directorio_destino))
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 os.makedirs(sub_directorio_destino)
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 ruta_completa = os.path.join(subdirectorio, archivo)
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 print(‘COPIANDO A: ‘+str(archivo))
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 shutil.copy(archivo, sub_directorio_destino)
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 registro.write(‘\n’+str(sub_directorio_destino)+’ ‘+str(fecha_backup))
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 else:
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 ruta_completa = os.path.join(subdirectorio, archivo)
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 print(‘COPIANDO A: ‘+str(archivo))
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 shutil.copy(archivo, sub_directorio_destino)
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 registro.write(‘\n’+str(sub_directorio_destino)+’ ‘+str(fecha_backup))

else:
print(‘VERIFIQUE EL DIRECTORIO’)
registro.write(‘\n’+’COMPUTADOR-OFFLINE-VERIFIQUE ‘+str(datetime.date.today()))

registro.close()

 

Este script adem谩s de crear copias de los archivos con sus respectivos subdirectorios, tambi茅n los registra en una bit谩cora (bitacora.txt), con la fecha de creaci贸n de la copia.

Bueno, no queda de m谩s aclararte que si quieres copiar estos c贸digos, ten en cuenta la identaci贸n, porque puede que al editar este art铆culo se me haya alterado algun espacio.


Valora este art铆culo:

C贸mo realizar backups con Python
5,0 rating based on 12.345 ratings
Overall rating: 5 out of 5 based on 1 reviews.

 

Name
Email
Review Title
Rating
Review Content

 

Super, muy bien

★★★★★
Muchas gracias por toda la informaci贸n
- Mar铆a Fernanda Acosta
Comparte esto en
Publicado en Backups.