Esse script realiza backup de bancos de dados MySQL e PostgreSQL. Os arquivos de backup são compactados e são preservados os “N” últimos arquivos de backup, conforme especificado na variável KEEP_DAYS. Os bancos a serem salvos devem ser especificados no arquivo CONF.
CÓDIGO
#!/usr/bin/python # -*- coding: UTF-8 -*- # Programa: backupdb.py # Função: Realiza backup de bancos de dados # Versão: 2.0 (salva databases individuais) # # Layout do arquivo conf # ---------------------- # SGBD SERVERNAME HOSTNAME USERNAME PASSWORD # (m|p) (srvname) (srv fqdn) (usr name) (usr pwd) # # SGBD........: m - mySql, p - PostgreSQL # SERVERNAME..: Nome do servidor (apenas para documentação) # HOSTNAME....: FQDN do servidor (usado para conectar ao banco) # USERNAME....: Userid para acesso ao banco # PASSWORD....: Password para o userid # # Dependencias # ------------ # - mysql # - mysqldump # - pg_dump # - psql # # OBS1: # Para o Postgre aceitar conexões externas, editar o arquivo pg_hba.conf # no servidor, incluindo a seguinte linha abaixo de "#IPv4 local connections" # # host all all /32 md5 # # OBS2: # Para backup do PostgreSQL é necessário criar um arquivo "/root/.pgpass", # considerando que esse script será executado pelo usuário "root", # com o seguinte conteúdo: # # #hostname:port:database:username:password # :5432:*:postgres: # # No arquivo conf, especificar o mesmo usuário do arquivo .pgpass, # no exemplo acima, "postgres". import commands import os, sys, time, glob #Parâmetros TEST = False # Flag teste CONF_FILE = "backupdb.conf" # Nome do arquivo conf BKP_DIR = "/mnt/data/backup/backupdb" # Dir. para arqs de backup LOG_DIR = "/mnt/data/backup/backupdb" # Dir. para arqs de log KEEP_DAYS = 3 # Nro. de dias a preservar #fim Parâmetros #Variáveis globais BASENAME = "" # Nome base p/ arquivo. def main(): global TEST, BASENAME, KEEP_DAYS, LOG_DIR, BKP_DIR #Trata caminhos dos arquivos BKP_DIR = BKP_DIR.strip() if (BKP_DIR.endswith("/") == False): BKP_DIR += "/" #endIf LOG_DIR = LOG_DIR.strip() if (LOG_DIR.endswith("/") == False): LOG_DIR += "/" #endIf #monta nome base do arquivo t = time.localtime(time.time()) BASENAME = "BKP%d%02d%02d" % (t[0], t[1], t[2]) logfile = LOG_DIR+BASENAME+".log" if not(TEST): #captura print para arquivo de log saveout = sys.stdout fsock = open(logfile, 'w') sys.stdout = fsock #endIf #Início printLogMsg("Inicio de execucao.") #Rotina de backup doBackup() #Remove arquivos antigos cleanUpFiles(BKP_DIR, "BKP*", KEEP_DAYS) #Fim printLogMsg("Fim de execucao.") if not(TEST): #Encerra captura do print sys.stdout = saveout fsock.close() #endIf #end main def doBackup(): """Realiza backup dos bancos de dados""" global CONF_FILE conf = os.path.dirname(sys.argv[0]) + "/" + CONF_FILE fconf = open(conf) #Processa backups a realizar for line in fconf: ln = line.split() if (len(ln) > 0): if (ln[0].lower() == "m"): doMySqlBkp(ln) elif (ln[0].lower() == "p"): doPostBkp(ln) #endIf #endIf #endFor fconf.close() #end doBackup def doMySqlBkp(args): """Realiza backup de banco MySQL""" global BASENAME, BPK_DIR #Nomes dos arquivos de backup e compactados bkpname = BKP_DIR+BASENAME+"_"+args[1]+"_My" tarname = BKP_DIR+BASENAME+"_"+args[1]+"_My.tar.bz2" msg = "Iniciando backup do servidor %s (MySQL)" % (args[1]) printLogMsg(msg) #Relaciona bancos de dados cmd = "mysql -h %s -u %s -p%s -Bse 'show databases'" % \ (args[2], args[3], args[4]) var = commands.getoutput(cmd) dbs = var.split("\n") for db in dbs: if (db.strip() != ""): fbkp = bkpname + "-" + db + ".sql" #Realiza backup printLogMsg("Fazendo dump do banco %s." % (db)) opt = db + " --skip-opt --add-lock" cmd = "mysqldump -h %s -u %s -p%s %s > %s" %\ (args[2], args[3], args[4], opt, fbkp) var = commands.getoutput(cmd) if (len(var.strip()) > 0): printLogMsg(var) #endIf #endIf #endFor #Compacta arquivo fbkp = bkpname + "-*" tarFile(fbkp, tarname) #end doMySqlBkp def doPostBkp(args): """Realiza backup de banco PostgreSQL""" global BASENAME, BKP_DIR #Nomes dos arquivos de backup e compactados bkpname = BKP_DIR+BASENAME+"_"+args[1]+"_Pg" tarname = BKP_DIR+BASENAME+"_"+args[1]+"_Pg.tar.bz2" msg = "Iniciando backup do servidor %s (PostgreSQL)" % (args[1]) printLogMsg(msg) #Relaciona bancos de dados cmd = "psql -h %s -U %s -q -c '\l'" % (args[2], args[3]) + \ " | sed -n 4,/\eof/p | grep -v rows\) | awk {'print $1'}" var = commands.getoutput(cmd) dbs = var.split("\n") for db in dbs: if (db.strip() != ""): fbkp = bkpname + "-" + db + ".sql" #Realiza backup printLogMsg("Fazendo dump do banco %s." % (db)) cmd = "pg_dump %s -h %s -U %s > %s" %\ (db, args[2], args[3], fbkp) var = commands.getoutput(cmd) if (len(var.strip()) > 0): printLogMsg(var) #endIf #endIf #endFor #Compacta arquivo fbkp = bkpname + "-*" tarFile(fbkp, tarname) #end doPostBkp #----- Funções Genericas ----------------------------------------------------- def cleanUpFiles(fdir, mask, age): """Remove arquivos que atendam o padrão 'mask' com mais de 'age' dias""" printLogMsg("Verificando remocao arquivos antigos...") #Data/Hora de corte tm = time.time() - (age * 60 * 60 * 24) #Processa arquivos que atendam ao padrão pattern = fdir + mask for fname in glob.glob(pattern): if (os.stat(fname).st_mtime < tm): fn = os.path.basename(fname) printLogMsg("Removendo arquivo: %s" % (fn)) os.remove(fname) #endIf #endFor #end cleanUpFiles def tarFile(fname, tarname): """Compacta arquivo e remove arquivo descompactado""" fn = os.path.basename(fname) printLogMsg("Iniciando compactação dos arquivos %s" % (fn)) #Compactar arquivo cmd = "tar -cjpf %s %s" % (tarname, fname) var = commands.getoutput(cmd) if (len(var.strip()) > 0): printLogMsg(var) #endIf #Remover arq. descompactado for fn in glob.glob(fname): os.remove(fn) #endFor #end tarFile def printLogMsg(msg): """Imprime mensagem de log com data e hora correntes.""" t = time.localtime(time.time()) lmsg = "%02d/%02d/%d %02d:%02d - %s" % (t[2], t[1], t[0], t[3], t[4], msg) print lmsg sys.stdout.flush() return #end printLogMsg if __name__ == "__main__": main()
backupdb.conf (exemplo)
# SGBD SERVERNAME SERVER_IP USERNAME PASSWORD m srvcos05 10.0.0.1 root 2006 p srvcos05 10.0.0.2 postgres