#!/bin/bash # Este programa faz backups das bases de dados de qq servidor e dos # arquivos do servidor local ou de arquivos montados via samba para um diretório # no servidor local. # Autor: Felipe Rafael Prenholato # Data: Wed Sep 6 21:52:35 BRT 2006 # E-Mail: philipe_rp@yahoo.com.br / chronos@gentoobr.org # Este script está coberto pela GPLv2. # Use por sua conta e risco. # Configure aqui o diretório onde serão arquivados os backups antigos. # BACKUP_ARCHIVE_ROOT='/opt/backup-archives' BACKUP_ARCHIVE_ROOT='/opt/backup-archives' # Configure aqui o tempo que os backups devem ficar arquivados, em dias. ARCHIVE_DAYS=3 # Configure aqui o diretório onde serão arquivos os backups atuais. # BACKUP_ROOT='/opt/backup' BACKUP_ROOT='/opt/backup' # Configure aqui os diretórios que terão seus backups feitos. Deve ser um por # linha. BACKUP_DIRS='/home/handrus /etc' # Configure aqui o diretório onde vai ser feito os dumps do Postgres. Ele ficara # dentro de $BACKUP_ROOT. PSQL_ROOT='pg-dump' # Configure aqui o host e a porta onde estão as bases do postgresql. # Serão feitos backups de todas as bases, uma com cada arquivo bzip2. # Mais de um host? Coloque um por linha. Precisa colocar porta, separe por ':', # ex: # PSQL_HOST='localhost:5432 # cerbero:666' PSQL_HOST='localhost:5432 local' # Configure aqui opções como porta e usuário do postgres por exemplo. # Estas confs são usadas para o psql e o pg_dump PSQL_OPTS='-U postgres' # Source /sbin/functions.sh pra deixar o script mais 'bonitinho' :]. # Quando rodar no cron e ir para o e-mail não vai ter cores e os caracteres aqui # vão todos certos. source /sbin/functions.sh # Umask default para o script umask 002 # Função para checar permissionamento do diretório. checaDir() { if [ -d $1 ] && [ -e $1 ] && [ -r $1 ] && [ -w $1 ] && [ -x $1 ] then eend 0 else if [ ! -d $1 ] && [ ! -e $1 ] then eend 1 echo " $(ewarn 'O diretório não existe, criando '$1)" mkdir -p $1 &>/dev/null sts=$? eend $sts if [ "$sts" != "0" ] then echo " $(eerror 'O diretório não pode ser criado, pode haver um arquivo com o mesmo nome ou não haver permissões para cria-lo')" exit 1 fi fi if [ ! -r $1 ] || [ ! -w $1 ] || [ ! -x $1 ] then eend 1 echo " $(eerror 'O diretório tem permissões incorretas.')" echo " $(eerror 'Use chmod para corrigir e rode o script novamente.')" fi fi } # Body do script ebegin "Checando $BACKUP_ARCHIVE_ROOT" checaDir $BACKUP_ARCHIVE_ROOT echo ebegin "Checando $BACKUP_ARCHIVE_ROOT/$PSQL_ROOT" checaDir $BACKUP_ARCHIVE_ROOT/$PSQL_ROOT echo ebegin "Checando $BACKUP_ROOT" checaDir $BACKUP_ROOT echo ebegin "Checando $BACKUP_ROOT/$PSQL_ROOT" checaDir $BACKUP_ROOT/$PSQL_ROOT # Backup start date BACKUP_START=$(date) echo ebegin "Iniciando backup em $BACKUP_START" # Arquivando backups de diretórios existentes ebegin "Arquivando backups de diretórios existentes" archs=$(find $BACKUP_ROOT -maxdepth 1 -type f -name '*.bz2') for e in $archs do echo " $(einfo 'Arquivando '$e)" mv $e* $BACKUP_ARCHIVE_ROOT &>/dev/null eend $? done # Arquivando backups de bases ebegin "Arquivando backups de bases de dados existentes" archs=$(find $BACKUP_ROOT/$PSQL_ROOT -type f -name '*.bz2') i=0 erro=0 for e in $archs do i=$(($i+1)) mv $e* $BACKUP_ARCHIVE_ROOT/$PSQL_ROOT >> $BACKUP_ARCHIVE_ROOT'/'$PSQL_ROOT'/archivelog' sts=$? [ "$sts" != "0" ] && erro=1 done if [ "$erro" == "1" ] then eend 1 echo " $(eerror 'Problemas no arquivamento das bases de dados.')" echo " $(eerror 'Log em '$BACKUP_ARCHIVE_ROOT'/'$PSQL_ROOT'/archivelog.')" else eend 0 echo " $(einfo $i' bases arquivadas.')" fi # Removendo os logs ebegin "Removendo os logs dos backups arquivados" find $BACKUP_ARCHIVE_ROOT -type f -name '*log' -exec rm {} \; &>/dev/null eend $? # Removendo backups arquivados com mais de $ARCHIVE_DAYS ebegin "Removendo backups velhos" archs=$(find $BACKUP_ARCHIVE_ROOT -type f -cmin $ARCHIVE_DAYS) i=0 erro=0 date >> $BACKUP_ARCHIVE_ROOT'/clearlog' for e in $archs do i=$(($i+1)) rm $e -f -v >> $BACKUP_ARCHIVE_ROOT'/clearlog' sts=$? [ "$sts" != "0" ] && erro=1 done if [ "$erro" == "1" ] then eend 1 echo " $(eerror 'Problemas na remoção dos arquivos antigos.')" echo " $(eerror 'Log em '$BACKUP_ARCHIVE_ROOT'/clearlog.')" else eend 0 echo " $(einfo $i' backup removidos.')" fi # Backup dos diretórios echo ebegin "Iniciando backup dos diretórios " for dir in $BACKUP_DIRS do bn=$(date +%Y%m%d_%Hh%Mm)${dir//\//-}'.tar.bz2' echo " $(einfo 'Backup de '$dir' em '$BACKUP_ROOT'/'$bn)" tar jcf $BACKUP_ROOT/$bn $dir &> $BACKUP_ROOT/$bn'.log' sts=$? if [ "$sts" != "0" ] then eend 1 echo " $(eerror 'Problemas no backup de '$dir'.')" echo " $(eerror 'Verifique o log em '$BACKUP_ROOT'/'$bn'.log.')" else eend 0 echo " $(einfo 'Gerando MD5')" md5sum $BACKUP_ROOT/$bn > $BACKUP_ROOT/$bn'.md5' 2>/dev/null eend $? fi done # Backup das bases de dados Postgres echo ebegin "Iniciando backup de bases Postgresql" PSQL_ROOT=$BACKUP_ROOT'/'$PSQL_ROOT for psqlhost in $PSQL_HOST do # Eu não usei cut -d: -f2 porque ele imprimia o mesmo que -f1. o awk retorna # uma string vazia. host=$(echo $psqlhost | awk -F: '{print $1}') textport=$(echo $psqlhost | awk -F: '{print $2}') count=$(echo $textport | wc -c) [ $count -gt 1 ] && port=" -p $textport " TMPDIR=$BACKUP_ROOT'/tmp_'$host [ ! -e $TMPDIR ] && mkdir $TMPDIR &>/dev/null TMPLST=$TMPDIR'/bdlist' echo " $(ebegin 'Backup de '$host$( [ $count -gt 1 ] && echo ' na porta '$textport))" echo " $(ebegin 'Testando acesso a '$host)" # Não filtro com cut aqui porque vai zoar o $? e eu não confio mto em # $PIPESTATUS psql $PSQL_OPTS -l -A -t -h $host $port &> $TMPLST sts=$? # Po ... fodeu ... kd o server O_o! if [ "$sts" != "0" ] then eend 1 echo " $(eerror 'O servidor '$host' não pode ser acessado.')" echo " $(eerror 'Verifique se o servidor postgres esta configurado corretamente.')" echo " $(eerror 'O acesso é feito via metodo trust e o usuário postgres deve estar')" echo " $(eerror 'habilitado para este IP. Conexões tcp/ip devem estar ativadas.')" else eend 0 # end para 'Testando acesso' # Para cada base do host faz o dump em um arquivo com o nome de # data_host_base.sql, ai compacta com bzip2 -z9 e depois faz um md5. for base in $(cat $TMPLST | cut -d'|' -f1 | egrep -v '^template[01]$') do bn=$(date +%Y%m%d_%Hh%Mm)'_'$host'_'$base'.sql' # Dumping echo " $(ebegin 'Dumping '$base' para '$bn)" pg_dump $PSQL_OPTS -h $host $port -O -i $base > $PSQL_ROOT/$bn 2> $PSQL_ROOT/$bn'.error_log' sts=$? if [ "$sts" != "0" ] then # Fodeu ... eend 1 echo " $(eerror 'Problemas no Dump da base.')" echo " $(eerror 'Log em '$PSQL_ROOT'/'$bn'.error_log')" else # Uha ... hora de compactar. eend 0 echo " $(ebegin 'Gerando '$bn'.bz2')" echo "bzip2" >> $PSQL_ROOT/$bn'.error_log' bzip2 -z9 $PSQL_ROOT/$bn >> $PSQL_ROOT/$bn'.error_log' 2>&1 sts=$? if [ "$sts" != "0" ] then # -_- ... echo " $(eerror 'Erro na compactação.')" echo " $(eerror 'Log em '$PSQL_ROOT'/'$bn'.error_log')" else echo " $(einfo 'Gerando md5')" md5sum $PSQL_ROOT/$bn.bz2 > $PSQL_ROOT/$bn'.bz2.md5' 2>/dev/null eend $? fi fi done fi rm -r $TMPDIR $TMPLST &>/dev/null done # Backup end date BACKUP_END=$(date) echo einfo "Backup terminado em $BACKUP_END" exit