Criando um Sistema de Backup Full e Diferencial com Python


O processo de Backup é vital para o funcionamento e segurança de qualquer ambiente corporativo. Uma vez que uma empresa não realize os processos adequados de backup, a mesma é vulnerável a vírus, falha de hardware do servidor, desastres naturais e até ataques de sequestro de dados com o Ransomware e etc. Manter esse tipo de processo, diariamente, semanalmente, mensalmente é de grande importância para o funcionamento do negócio e processos de Recuperação de Desastres. Hoje neste artigo estarei mostrando um projeto bem simples que escrevi para realizar backups diários e semanais do File Server da empresa em que trabalho utilizando como base um servidor Linux rodando o Samba feito em Python.. Mas pode ser aplicado em qualquer caso, desde que a base seja Linux.

'Puts, se é pra fazer isso, porque não fez em Shell Script que era mais rápido?'

Calma, se você se sente mais a vontade para realizar esse tipo de rotina, saiba que você não está sozinho. Inclusive esse post que você está lendo foi baseado em outro que eu fiz há uns meses aqui no blog abordando o mesmo processo de backup, porém com Shell Script. Você pode acessar o artigo clicando aqui. :)

Baixando o Projeto 

Git do Projeto: https://github.com/msfidelis/PythonBackupSystem/

Você pode fazer o clone do projeto normalmente
 # git clone https://github.com/msfidelis/PythonBackupSystem.git  

Neste projeto, pelo menos nesta versão, serão baixadas dois arquivos .py e o Readme que pode ser ignorado por enquanto.


Realizando Backup Full com Python

O Backup Full do fileserver ou aplicação é essencial de ser efetuado semanalmente, mensalmente, quinzenalmente ou até diariamente para garantir a disponibilidade e integridade das informações corporativas. Portanto esse script pode demorar segundos, minutos e até dias dependendo da quantidade de informação que você esteja manipulando. No meu caso, os backups fulls serão feitos semanalmente, e os diários serão tratados por Rsync mais a frente :D.

Gerando o arquivo de Backup

Vamos começar pelo mais simples dos backups, o Backup Full. Esse script foi construído para compactar 4 TB do fileserver da minha empresa em um aquivo tar.gz. Por mais que a quantidade de dados seja realmente grande, o script é muito simples. Abrindo o mesmo, podemos ir direto na função gerabackup(). Essa função, assim como o código completo está bem comentado e quase nem precisa desse post para ser entendido, e ela server pra retornar a string que será executada na Shell e irá compactar o todo o file server em outro diretório. Editando essa função, você deverá alterar as variáveis backupfile se quiser trocar o nome do arquivo de backup, pathdestino para o local que será armazenado o arquivo de backup e pathorigem para o local que será backupeado. Mais detalhes abaixo.No final ele vai retornar a string que será executada montada.

 # vim backup-full.py  


#CONSTROI O ARQUIVO E PATH DE BACKUP E RETORNA
def gerabackup():
date = (time.strftime("%Y-%m-%d"))
backupfile = '%s-backup-full.tar.gz' % date # Cria o nome do arquivo de Backup
pathdestino = '/mnt/hdbackup/%s' % backupfile # Destino onde será gravado o Backup
pathorigem = '/mnt/storage/' # pasta que será 'backupeada'
backup = 'tar cvf %s %s' % (pathdestino, pathorigem) # Comando de execução
return backup
view raw gerabackup.py hosted with ❤ by GitHub

Diretório de logs

Dei uma trabalhada extra nesse script pra ele gerar Logs bacanas pra ter um controle melhor do tempo que foi levado para a criação do backup. Você pode alterar o diretório que o mesmo será armazenado editando a função geralog(). Aqui você precisa se atentar com dois detalhes: Primeiro a variável pathlog que irá armazenar todos os logs do sistema. Modifique a vontade, mas garanta que o diretório exista. Caso não exista, crie o mesmo antes de prosseguir com o primeiro Backup e também a logfile que irá definir o nome do arquivo de backup. Todos os backups, tanto o full que estamos tratando quanto o diferencial, serão guardados e organizados pela data. Então nesse caso, o logfile será criado como ano-mes-dia-tipodobackup.txt. Ex: 2016-01-31-backup-full.txt. No final ele também retornará uma string com que será executada como comando pela shell do Python logo a diante.

Criando os diretórios default para os logs:
 # mkdir -p /var/log/backup/backup-full  



#CONSTROI OS LOGS DO SISTEMA - Aqui selecionamos o nome do backup e o arquivo de logs que iremos criar.
def geralog():
date = (time.strftime("%Y-%m-%d")) #
logfile = '%s-backup-full.txt' % date # Cria o arquivo de Log
pathlog = '/var/log/backup/backup-full/%s' % logfile # Arquivo de log
return pathlog
view raw geralog.py hosted with ❤ by GitHub
Função 'Core' do Backup Full

Se você seguiu os dois passos anteriores alterando e adequando o backup para sua necessidade, essa função não deverá ser alterada em nada, somente a variável 'disk' caso seu backup esteja sendo enviado para um HD ou partição extra. Só coloquei ela aqui pra explicar melhor como o Backup funciona.
Essa função pega todos os valores retornados pelas duas funções anteriores e cria a sequencia de backup e geração de logs em si iniciando todos as strings retornadas dentro de um subprocess.call() que abre uma 'sub shell' com o usuário que está rodando o script e executa tudo nela. Como vocês puderam perceber, esse script foi escrito com base em Linux, então será executado tudo numa espécie de bash :D


#CRIA OS BACKUPs
def backupfull():
disk = '/dev/sdb' #Define onde está a partição que será usada para guardar o backup
horaInicio = time.strftime('%H:%M:%S')
pathlog = geralog()
backup = gerabackup()
log = ' >> %s' % pathlog
start = inicio(horaInicio)
#Printa o Banner
l = open(pathlog, 'w')
l.write(start)
l.close()
#Monta todos os discos que estão no FSTAB
mount = 'mount -a'
subprocess.call(mount, shell=True)
#RODA O BACKUP
subprocess.call(backup + log, shell=True)
#Printa o final e relatório
diaInicio = (time.strftime("%d-%m-%Y"))
final = termino(diaInicio, horaInicio, backup, pathlog)
r = open(pathlog, 'w')
r.write(final)
r.close()
#Descomente essa função para desmontar a partição que será utilizada para armazenar o backup
desmonta_hd(disk)
view raw backupfull.py hosted with ❤ by GitHub

Você deverá se atentar com uma coisa apenas: A função desmonta_hd(). Ela tem a função de desmontar o disco que está na variário disk. Portanto, se por um caso de segurança seja necessário desmontar o HD após o termino do Backup, descomente essa função e o resto estará tudo Ok :D. Deixar ela comentada por default.

No caso a função desmonta_hd só executa uma rotina normal do Linux, a umount, como vocês podem ver:

#ESSA FUNÇÃO DESMONTA O HD DE BACKUP POR SEGURANÇA.
#DESCOMENTE A LINHA desmonta_hd() DENTRO DE backupfull() PARA UTILIZÁ-LA
def desmonta_hd(disk):
try:
umount = 'umount %s' % disk
subprocess.call(umount, shell=True)
return True
except:
return False
view raw desmontahd.py hosted with ❤ by GitHub




Rodando o Backup

Para todar o Backup é muito simples. Você pode utilizar o Shebang da primeira linha ou utilizar o próprio Python diretamente:
 # ./backup-full.py   
 ou  
 # python backup-full.py  


acompanhando os logs com o Tails podemos ver que o mesmo foi salvo na pasta /var/log/backups/backup-full como planejado, e o mesmo contém todos os arquivos que foram compactados.


Realizando Backup Diferencial com Python

O backup diferencial é um backup que realiza a cópia somente do que foi modificado a partir de um backup full realizado anteriormente, mantendo um log de tamanho, permissão, arquivos novos, deletados e etc, e por meio do Rsync, ele manipula somente esses arquivos, afim de manter uma base idêntica a de 'produção'. Esse tipo de backup é criado para ser realizado diariamente. 

Agora vamos tratar do arquivo backup-diferencial.py que está no mesmo diretório do clone. 
 # vim backup-diferencial.py  

Configurando o Backup

Você vai perceber, se não caiu diretamente aqui sem ler o anterior por razões particulares, que os dois backups foram estruturados praticamente da mesma forma. O arquivo que gera o backup, também retorna uma string que será executada pela shell do linux por uma função 'core' do sisteminha. Porém esse tipo de backup é só um pouquinho mais complicado que o full. Teremos que nos atentar com algumas variáveis a mais pra construir a string de execução.

Começando com as mais simples, precisamos definir o pathorigem e o pathdestino, que respectivamente vão ser a origem (local que será copiado) e destino (local que irá armazenar o espelho).
A opção exclude será utilizada para dizer ao Rsync para ignorar determinados tipos de arquivos, como arquivos .tmp, .log e etc. Fica a seu critério. E a variável opts ficará responsável por armazenar os parâmetros do Rsync. Eu sei que são vários, mas no começo do script você poderá ver uma série de linhas comentadas com um mini 'manualzinho' que eu fiz pra ajudar vocês em qual opção escolher em determinado tipo de caso.


#CONSTROI O ARQUIVO E PATH DE BACKUP E RETORNA
def gerabackup():
date = (time.strftime("%Y-%m-%d"))
opts = 'Cravzp'
#opts = 'rvtl' # Opções que serão passadas com Rsync. Comentários no inicio do Script :)
exclude = '*.log, *.tmp, .recycle' # Define os diretórios e tipos de arquivos que não vão ter backup
pathdestino = '/mnt/backupclone/' # Destino onde será gravado espelhado o backup
pathorigem = '/mnt/storage/' # pasta que será 'backupeada'
backup = 'rsync -%s --exclude={%s} %s %s' % (opts, exclude, pathorigem, pathdestino) # Comando de execução
#print backup
#sys.exit()
return backup
view raw gerarync.py hosted with ❤ by GitHub


Configurando os Logs

Assim como a o script anterior, esse script também tem uma função que constrói o arquivo de logs que é organizado por ano-mes-dia-tipobackup.txt. Aqui temos que nos atentar também ao pathlog, pois nele será criado o nosso log com tudo que ocorreu durante o backup. Então é aconselhável que o mesmo aponte para um local que já exista, caso não, crie antes de testar o primeiro backup.
 # mkdir -p /var/log/backup/backup-rsync/  

#CONSTROI OS LOGS DO SISTEMA - Aqui selecionamos o nome do backup e o arquivo de logs que iremos criar.
def geralog():
date = (time.strftime("%Y-%m-%d")) #
logfile = '%s-backup-rsync.txt' % date # Cria o arquivo de Log
pathlog = '/var/log/backup/backup-rsync/%s' % logfile # Arquivo de log
return pathlog
view raw logrync.py hosted with ❤ by GitHub


Função principal do Rsync

Essa função backupclone() não precisa ser alterada por default, a menos, que como no script anterior de backup full. Nela você precisa definir a partição ou disco externo que será utilizado para armazenar o backup, mais especificamente na variável 'disk'. Caso seja necessário que o HD que guarda o Backup seja desmontado por segurança, descomente a linha que chama a função desmonta_hd().


#CRIA OS BACKUPs
def backupclone():
disk = '/dev/sdc' # Aqui defina a partição que contém o disco que será realizado para guardar o backup
horaInicio = time.strftime('%H:%M:%S')
pathlog = geralog()
backup = gerabackup()
log = ' >> %s' % pathlog
start = inicio(horaInicio)
#Printa o Banner
l = open(pathlog, 'w')
l.write(start)
l.close()
#Monta todos os discos presentes no fstab
mount = 'mount -a'
subprocess.call(mount, shell=True)
#RODA O BACKUP
subprocess.call(backup + log, shell=True)
#Printa o final e relatório
diaInicio = (time.strftime("%d-%m-%Y"))
final = termino(diaInicio, horaInicio, backup, pathlog)
r = open(pathlog, 'w')
r.write(final)
r.close()
#Caso seja necessário que o HD que guarda o Backup seja desmontado por segurança, descomente essa linha
#desmonta_hd(disk)
view raw backupclone.py hosted with ❤ by GitHub

 Rodando o Backup clone

Para rodar o Script é bem simples. Mas garanta que todo os diretórios estejam bem configurados. Se tudo der certo, um log será criado na pasta /var/log/backup/backup-rsync/ com todos os dados de tudo que ocorreu durante o backup.
 # ./backup-diferencial.py   
 ou  
 # python backup-diferencial.py  


Agendando o Backup com Crontabs

Estruturando as pastas de Backup.

Para criarmos uma arquitetura de backup organizada, vamos primeiro criar um diretório para armazenar os scripts de backup antes de configurar o Cron para executá-los periodicamente. No caso, criarei a pastas em /var/scripts/backup
 # mkdir -p /var/scripts/backup  

agora vamos copiar os arquivos modicados para dentro dessa pasta:
 # cp backup-* /var/scripts/backup  

Criando as Crontabs

Neste exemplo, o backup diferencial será executado todos os dias (segunda a sexta) às 23h00 para manter uma base diária de modificações e o backup full será executado às 23h30 de todos os sábados pois é um processo que consome bem mais processamento e memória do servidor no fim das contas. Caso sinta dificuldade de entender e customizar suas crontabs, leia este artigo Aqui.
 # crontab -e   
 #De todas as segundas até sexta, 23h00 independente do dia ou do mês será executado o backup diferencial :D  
 00 23 * * 1-5 /var/scripts/backup/backup-diferencial.py  
   
 #Todas as sextas feitas, 23h30 será iniciado o processo de backup full   
 # 00 00 * * 5 /var/scripts/backup/backup-full.py  

Salve e divirta-se



    Blogger Comment
    Facebook Comment

0 comments:

Postar um comentário