… ou YASHTBODB: Yep, Another Shell Script To Backup Oracle DataBase!

Já faz algum tempo que utilizo Shell Script para fazer backup no Oracle. Na verdade eu prefiro utilizar outras linguagens de programação, particularmente o PERL, para não precisar ficar chamando o SQL*Plus toda hora. Mas como existe uma barreira cultural por aqui, acabou ficando tudo em Shell Script mesmo. Bom, ocorre que chegou a hora de aposentá-los em favor do RMAN. Sim, com o uso do RAC junto com o ASM, backup manual ou “user managed backup” como a Oracle gosta de dizer, perdeu completamente o sentido. Além disso, no Oracle 10g, o Database Control implementou uma série de alertas sofisticados bem mais eficientes que o singelo script aqui em questão. Estou terminando de implantar o RMAN para todos os últimos servidores e então os últimos scripts cairão finalmente no ostracismo. Então estou publicando-os aqui, para que sirvam de referência futura.

Requisitos

Rotinas executadas a cada 30 minutos:

Rotinas executadas a cada 24 horas:

Rotinas executadas a cada 7 dias:

Rotina mensal (realizadas no último dia de cada mês):

Outros requisitos:

Preparação

Antes de mais nada, é preciso criar um usuário no SO e no Oracle. É preciso se assegurar que o usuário em questão tenha acesso às pastas que ele irá copiar. Existem pelo menos umas 4 formas de se fazer isso:

Para criar um usuário no SO que faça parate do grupo ‘oinstall’ (realmente estou supondo que você usou o nome dos usuários e grupos de usuáros padrões da instalação):

/usr/sbin/useradd -m -p senha -g oinstall -c 'Usuário que dispara os scripts de backup' backup

O mesmo usuário do SO deverá ter um correspondente dentro do banco de dados:

CREATE USER backup IDENTIFIED BY senha
  DEFAULT TABLESPACE users
  QUOTA UNLIMITED ON users
;

Se você quiser utilizar um usuário a parte mas não quer colocar a senha do usuário nos scripts (que é o que foi feito no nosso exemplo), pode criar o usuário com o comando abaixo:

CREATE USER backup IDENTIFIED EXTERNALLY
  DEFAULT TABLESPACE users
  QUOTA UNLIMITED ON users
;

Mas para utilizar usuários autenticados externamente (pelo SO) não esqueça de setar no ‘init.ora’ os seguintes parâmetros:

remote_os_authent=FALSE
os_authent_prefix=''

O parâmetro ‘os_authent_prefix’ é opcional e permite que o nome no SO seja idêntico ao nome no banco de dados. Já o parâmetro ‘remote_os_authent’ é vital para garantir a segurnaça do banco de dados. O padrão do parâmetro é ‘FALSE’ e ninguém em sã consciência utiliza este parâmetro como ‘TRUE’.

Depois de criar o usuário precisamos conceder as permissões adequadas para ele:

GRANT CREATE SESSION TO backup;
GRANT ALTER SESSION TO backup;
GRANT ALTER DATABASE TO backup;
GRANT ALTER SYSTEM TO backup;
GRANT MANAGE TABLESPACE TO backup;
GRANT ANALYZE ANY TO backup;
GRANT ANALYZE ANY DICTIONARY TO backup;
GRANT EXP_FULL_DATABASE TO backup;

Lembre-se de O usuário também deve ter um tablespace com alguma quota para criar as tabelas de logs do backup lógico (coisas do data pump a partir do 10g). O comando CREATE USER cria o usuário, com a senha: ‘senha’. Depois concedemos privilégio para o usuário se conectar no banco de dados em CREATE SESSION. O privilégio ALTER SESSION será utilizado para ajudar a identificar o backup lógico do control file enquanto o privilégio ALTER DATABASE é utilizado para realizar o backup físico e lógico do control file propriamente dito. O privilégio ALTER SYSTEM é necessário para realizar o checkpoint e o rotacionamento dos logs durante o backup físico on line enquanto o privilégio MANAGE TABLESPACE permite a operação de backup on line propriamente dita. Note que aqui a permissão de leitura dos datafiles pelo usuário do SO é necessária também. Depois temos os privilégios ANALYZE e ANALYZE ANY DICTIONARY necessários para as atualizações de estatísticas das tabelas e índices. Note que o privilégio ANALYZE ANY DICTIONARY surge apenas no Oracle 10g, não existindo nem sendo necessário em versões anteriores. Por último vem o privilégio EXP_FULL_DATABASE que é necessário para o backup lógico.

Se você for utilizar o Data Pump (muito recomendado e utilizado no nosso exemplo), a nova ferramente de backup lógico da Oracle a partir da versão 10g, você deverá utilizar também os seguintes comandos SQL:

CREATE DIRECTORY data_pump_dir_ORACLE_SID AS '/u03/app/oracle/admin/ORA_SID/exp';
GRANT READ, WRITE ON DIRECTORY data_pump_dir_ORA_SID

Onde ‘ORACLE_SID’ é o nome do seu banco de dados oracle. É claro que o ponto de montagem ‘/u03’ é específico do padrão que adoto nos meus servidores. Substitua o caminho do diretório para aquele que você reservou no seu servidor. Lembre-se que este diretório deve ser criado manualmente e o usuário ‘backup’ ou o grupo ‘oinstall’ do SO devem ter permissões de leitura e gravação neste diretório:

mkdir -p /u03/app/oracle/admin/ORA_SID/exp
chown backup:oinstall /u03/app/oracle/admin/ORA_SID/exp
chmod 755/u03/app/oracle/admin/ORA_SID/exp

Outras permissões deverão ser acertadas para o usuário de backup no SO como a permissão para apagar os archives (com uma permissão 770 na pasta por exemplo). Alguns acertos podem ser um pouco chatos e devem ser realizados no servidor de destino onde os arquivos são copiados também.

Um último detalhe é que é preciso configurar o SSH sem senha entre os servidores onde está o servidor Oracle e e o que vai receber todos os backups. Meus testes com NFS mostraram que ele é menos estável que o SSH e a diferença de performance é mínima. Existem vários tutoriais sobre como fazer isso, inclusive este da própria Oracle. No meu caso eu criei um usuário backup e um usuário oracle no servidor de destino e gerei o ssh sem senha entre os usuários com mesmo nome nos servidores de origem e destino dos backups.

Funcionamento do Script

Algumas premissas foram assumidas antes de criar o script:

Variáveis de Ambiente

Antes de passar para os scripts de backup, segue abaixo algumas variáveis utilizadas não apenas pelos scripts em shell, como também os scripts em SQL. Vale a pena lembrar que quando os scripts são executados no modo não interativo (como quando chamados pelo cron) é comum que os arquivos .bashrc e .bash_profile ignorem suas configurações. Por via das dúvidas, vamos exportar todas as variáveis de ambiente do Oracle e outros que serão úteis em nossos scripts.

Chamadas no crontab

Segue aqui as chamadas utilizadas para acionar o script

00 06 1 * * /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base rotina_mensal
00 22 * * * /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base backup_noturno
00,30  * * * * /bin/bash /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base copia_archives

Note que para realizar as rotinas de backup off line, é preciso do privilégio de SYSDBA para fechar e abrir a instância. Então se você utiliza um usuário separado para o backup, deverá colocar a linha abaixo no crontab do usuário oracle do SO e não usuário backup.

00 00 * * 0 /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base backup_off_line

O Script

Bom, chega de enrolação, segue abaixo o script. Se você encontrar algum erro (eu tive que tirar algumas coisas muito específicas aqui do trabalho) ou alguma forma de melhorar ele, por favor deixe um comentário ou mande um e-mail.

#!/bin/bash
######################################################################################
#	Arquivo: backup.sh                                                           #
#	Uso: Script para backup "user managed" de bancos de dados Oracle             #
#	Criado por: Fábio Telles                                                     #
#	Última alteração: 14/08/2008                                                 #
#	Motivo: Publicação                                                           #
######################################################################################
#	TODO: Refazer todo script em PERL ;-)                                        #
######################################################################################

# Verificação de parâmetros
ORACLE_SID=$1
operation=$2
if [ -z $operation ]; then
  echo "***** Favor definir a operação a ser executada"
  echo "***** chamada $0 $* ilegal"
  echo "***** uso: $0  "
  exit 2
fi
if [ -z $ORACLE_SID ]; then
  echo "***** Favor definir o nome do banco de dados"
  echo "***** chamada $0 $* ilegal"
  echo "***** uso: $0  "
  exit 2
fi

# Definição de variáveis (variáveis referenciadas fora do script precisam ser exportadas)
export ORACLE_SID
export ORACLE_BASE=/opt/app/oracle
export ORACLE_HOME=${ORACLE_BASE}/product/10.2.0/db_1
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib
export SQLPATH=/u01/app/oracle/admin/${ORACLE_SID}/adhoc
export NLS_LANG=Portuguese_Brazil.WE8ISO8859P1
export PATH=$PATH:${ORACLE_HOME}/bin
export dia=`date +%Y-%m-%d`
export log=/u01/app/oracle/admin/${ORACLE_SID}/backup/${operation}_${dia}.log
export arch_dest=/u02/app/oracle/admin/${ORACLE_SID}/arch
export dump_dest=/u03/app/oracle/admin/${ORACLE_SID}/exp
export remote_dest=seu_servidor_backup
dados=(/u04 /u05)
oracle_mail=email_do_dba@sua_empresa.com.br

# Uma função para cada rotina
copia_archives() {
  rsync -t ${arch_dest}/* ${remote_dest}:${arch_dest} 2>> $log
  if [ $? -ne 0 ]; then
    cat $log | mail -s "Erros na cópia de archives de `uname -n` p/ $remote_dest em ${dia}" $oracle_mail
  fi
}

verifica_discos() {
  # Verifica se alguma partição montada tem mais de 80% e 95% de ocupação
  for part in `df -hlP -t ext3 | cut -c0-9` ;do
    df $part > /dev/null 2> /dev/null
    if [ $? -eq 0 ]; then
      mount=`df $part | tail -1 | awk '{print $6}'`
      percent=`df $part | tail -1 | awk '{print $5}'`
      if [ ${percent%%} -gt 80 -a ${percent%%} -lt 95 ]; then
        echo "Atenção: `uname -n` c/ $part montada em $mount está c/ $percent ocupado." >> $log
        cat $log | mail -s "Alerta de disco em `uname -n`!" $oracle_mail
      elif [ ${percent%%} -ge 95 ]; then
        echo "ATENÇÃO URGENTE: `uname -n` c/ $part montada em $mount está c/ $percent ocupado." >> $log
        cat $log | mail -s "ALERTA CRÍTICO de disco em `uname -n`!" $oracle_mail
     fi
    fi
  done
}

analize() {
  echo "Analyze: analizando ${ORACLE_SID} em "`date +%R:%S` >> $log
  sqlplus -S / <> $log 2>> $log
}

backup_logico() {
  echo "Backup lógico: removendo exports de ${dump_dest} em "`date +%R:%S` >> $log
  rm -v ${dump_dest}/${ORACLE_SID}_full_* >> $log 2>> $log
  echo "Backup lógico: export iniciado em "`date +%R:%S` >> $log
  expdp / full=y directory=data_pump_dir_${ORACLE_SID} dumpfile=${ORACLE_SID}_full_${dia}.dmp
    logfile=${ORACLE_SID}_full_exp_${dia}.log
  tail -n 1 ${dump_dest}/${ORACLE_SID}_full_exp_${dia}.log >> $log 2>> $log
  echo "Backup lógico: copiando dump para ${remote_dest}/${dump_dest}  em "`date +%R:%S` >> $log
  scp ${dump_dest}/${ORACLE_SID}_full_${dia}.dmp
    ${remote_dest}:${dump_dest}/${ORACLE_SID}_full_${dia}.dmp >> $log 2>> $log
  scp ${dump_dest}/${ORACLE_SID}_full_exp_${dia}.log
    ${remote_dest}:${dump_dest}/${ORACLE_SID}_full_exp_${dia}.log >> $log 2>> $log
  echo "" >> $log
}

verifica_data_file() {
  echo "Verificação física on-line iniciada em "`date +%R:%S` >> $log
  sqlplus -S / <> ${SQLPATH}/db_verify.log'
      FROM dba_data_files
      ORDER BY tablespace_name, file_name;
    SPOOL OFF
    @db_verify.txt
    EXIT
EOF_VERIFICA_DATA_FILE
  egrep --color -n -B 7 -A 9 'Total Pages Failing.*(Data).*[^0]$'
    ${SQLPATH}/db_verify.log >> $log 2>> $log
  egrep --color -n -B 9 -A 7 'Total Pages Failing.*(Index).*[^0]$'
    ${SQLPATH}/db_verify.log >> $log 2>> $log
  egrep --color -n -B 14 -A 2 'Total Pages Marked Corrupt.*[^0]$'
    ${SQLPATH}/db_verify.log >> $log 2>> $log
  echo "" >> $log 2>> $log
}

backup_fisico_on_line() {
  echo "Backup físico on-line: copiando data files para ${remote_dest} em "`date +%R:%S`  >> $log
  sqlplus -S / <> $log'   command
          FROM
            dba_data_files  a,
            dba_tablespaces b
          WHERE
            a.tablespace_name = b.tablespace_name AND
            b.contents != 'TEMPORARY'
        UNION
        SELECT
          '4' ordem,
          tablespace_name,
          'ALTER TABLESPACE ' || tablespace_name || ' END BACKUP;' command
          FROM dba_tablespaces
          WHERE contents != 'TEMPORARY'
      )
      ORDER BY tablespace_name, ordem;
    SELECT 'ALTER SYSTEM ARCHIVE LOG CURRENT;' FROM dual;
    SELECT 'EXIT;' FROM dual;
    SPOOL OFF
    SET PAGES 50
    SPOOL ${SQLPATH}/backup_on_line.log
    @${SQLPATH}/backup_on_line.txt
    SPOOL OFF
EOF_BACKUP_ON_LINE
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_on_line.txt >> $log 2>> $log
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_on_line.log >> $log 2>> $log
  echo "" >> $log
}

compara_backup_fisico() {
  echo "Backup físico on-line: comparando origem e destino em "`date +%R:%S`  >> $log
  echo "Backup físico on-line: origem =" >> $log 2>> $log
  for p in ${dados[*]}; do
    du -hs ${p}/oradata/${ORACLE_SID} --exclude temp* >> $log 2>> $log
  done
  echo "Backup físico on-line: destino =" >> $log 2>> $log
  for p in ${dados[*]}; do
    ssh $remote_dest du -hs ${p}/oradata/${ORACLE_SID} >> $log 2>> $log
  done
  echo "" >> $log
}

backup_control_file() {
  echo "Backup físico on-line: copiando control files para ${ORACLE_HOME}/dbs em "`date +%R:%S`  >> $log
  sqlplus -S / <> $log'
      FROM
        v$parameter par,
        v$instance ins,
        v$process pro,
        v$session ses
      WHERE
        par.name='user_dump_dest' AND
        ses.sid = SYS_CONTEXT ('USERENV', 'SID') AND
        ses.paddr = pro.addr
     ;
    SPOOL OFF
    SPOOL ${SQLPATH}/backup_control_file.log
    ALTER SESSION SET TRACEFILE_IDENTIFIER = 'control_file';
    ALTER DATABASE BACKUP CONTROLFILE TO TRACE;
    ALTER SESSION SET TRACEFILE_IDENTIFIER = '';
    @${SQLPATH}/backup_control_file.txt
    ALTER DATABASE BACKUP CONTROLFILE TO '${ORACLE_HOME}/dbs/control_file_back.bin' REUSE;
    SPOOL OFF
EOF_BACKUP_ON_LINE
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_control_file.txt >> $log 2>> $log
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_control_file.log >> $log 2>> $log
  echo "" >> $log
}

backup_dbs() {
  echo "Backup físico on-line: copiando ${ORACLE_HOME}/dbs para
    ${remote_dest}:${ORACLE_HOME}/dbs_${ORACLE_SID}.tar.bz2 em "`date +%R:%S`  >> $log
  cd $ORACLE_HOME
  tar -cjf ${SQLPATH}/dbs_${ORACLE_SID}.tar.bz2 dbs >> $log 2>> $log
  scp ${SQLPATH}/dbs_${ORACLE_SID}.tar.bz2
    ${remote_dest}:${SQLPATH}/dbs_${ORACLE_SID}.tar.bz2 >> $log 2>> $log
}

limpa_archives() {
  echo "Archives: removendo archives com mais de 8 dias de $arch_dest em "`date +%R:%S` >> $log
  find $arch_dest -daystart -mtime +8 -exec rm -fv {} ; >> $log 2>> $log
  echo "" >> $log
}

verifica_alert() {
  echo "Alert: erros encontrados =>" >> $log
  egrep --color -n -B 2 '(ORA-|SP2-)'
    /u01/app/oracle/admin/${ORACLE_SID}/bdump/alert_${ORACLE_SID}.log >> $log 2>> $log
  echo "Alert: renomeando bdump/alert_${ORACLE_SID}.log para ${ORACLE_SID}_${dia}.log" >> $log
  if [ -f /u01/app/oracle/admin/${ORACLE_SID}/bdump/alert_${ORACLE_SID}.log ]; then
    mv /u01/app/oracle/admin/${ORACLE_SID}/bdump/alert_${ORACLE_SID}.log
      /u01/app/oracle/admin/${ORACLE_SID}/bdump/${ORACLE_SID}_${dia}.log >> $log
  fi
}

verifica_tablespaces() {
  echo "Tablespaces com mais de 80% de espaço ocupado =>" >> $log
  sqlplus -S / < 80
    UNION
    SELECT
      tablespace_name || ' com ' ||
        TO_CHAR( 100 * SUM (user_bytes) / SUM (DECODE (autoextensible, 'NO', bytes, maxbytes)) , '999.9')
        || '% ocupado' tablespace
      FROM dba_temp_files
      GROUP BY tablespace_name
      HAVING 100 * SUM(user_bytes) /  SUM (DECODE (autoextensible, 'NO', bytes, maxbytes)) > 80
    ;
    SPOOL OFF
    EXIT;
EOF_VERIFICA_TABLESPACES
  cat ${SQLPATH}/verifica_tablespaces.log >> $log 2>> $log
}

mostra_espaco_disco() {
  echo "Espaço em disco =>" >> $log
  df -hl -t ext3 >> $log 2>> $log
  echo "" >> $log
}

backup_spfile() {
  echo "Copiando spfile para ${ORACLE_HOME}/dbs/init${ORACLE_SID}_backup.ora em "`date +%R:%S` >> $log
  #Só funciona se o spfile existir
  if [ -f ${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora ]; then
    #Só pode ser executado pelo usuário Oracle do SO. Verificação abaixo
    if [ $USER != 'oracle' ]; then
      echo "***** A operação ${operation} não é válida com o usuário $USER" >> $log
      echo "***** tente novamente com o usuário oracle do SO." >> $log
      exit 2
    fi
    echo " --Backup do spfile (precisa de privilégio sysdba ou sysoper)"
    sqlplus -S / as sysdba <> $log 2>> $log
  else
    echo "SPFILE ${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora não encontrado!" >> $log
  fi
}

shut_down() {
  echo "Backup físico off line: desligando instância em "`date +%R:%S` >> $log
  #Só pode ser executado pelo usuário Oracle do SO. Verificação abaixo
  if [ $USER != 'oracle' ]; then
    echo "***** A operação ${operation} não é válida com o usuário $USER" >> $log
    echo "***** tente novamente com o usuário oracle do SO." >> $log
    exit 2
  fi
  sqlplus -S / as sysdba <> $log 2>> $log
  proc=`ps -ef | egrep pmon_$ORACLE_SID  | grep -v grep`
  if [ -n $proc ]; then
    echo "***** Problema ao desligar a instância $ORACLE_SID" >> $log
    echo "***** Tentando realizar um shutdown abort" >> $log
    sqlplus -S / as sysdba <> $log 2>> $log
    proc=`ps -ef | egrep pmon_$ORACLE_SID  | grep -v grep`
    if [ -n $proc ]; then
      echo "***** Algum problema sério aconteceu no banco $ORACLE_SID" >> $log
      echo "***** O servidor pode estar num estado inconsistente" >> $log
      cat $log | mail -s "URGENTE!!! Erro no backup off line de `uname -n`/$dia" $oracle_mail
      exit 2
      grep --color -n -B 2 ORA- ${SQLPATH}/shut_down_abort.log >> $log 2>> $log
    fi
  fi
  echo "" >> $log 2>> $log
}

copia_datafiles() {
  echo "Backup físico of line: copiando arquivos de dados em "`date +%R:%S` >> $log
  for p in ${dados[*]}; do
    scp ${p}/oradata/${ORACLE_SID}/* ${remote_dest}:${p}/oradata/${ORACLE_SID} 2>> $log
  done
}

start_up() {
  echo "Backup físico: ligando instância em "`date +%R:%S` >> $log
  #Só pode ser executado pelo usuário Oracle do SO. Verificação abaixo
  if [ $USER != 'oracle' ]; then
    echo "***** A operação ${operation} não é válida com o usuário $USER" >> $log
    echo "***** tente novamente com o usuário oracle do SO." >> $log
    exit 2
  fi
  sqlplus -S / as sysdba <> $log 2>> $log
  if [ $? -eq 0 ]; then
    echo "***** Problema ao ligar a instância $ORACLE_SID" >> $log
    cat $log | mail -s "URGENTE!!! Erro no backup off line de `uname -n`/$dia" $oracle_mail
    exit 2
  else
    proc=`ps -ef | egrep pmon_$ORACLE_SID  | grep -v grep`
    if [ -z $proc ]; then
      echo "***** Problema ao ligar a instância $ORACLE_SID" >> $log
      cat $log | mail -s "URGENTE!!! Erro no backup off line de `uname -n`/$dia" $oracle_mail
      exit 2
    fi
  fi
  echo "" >> $log
}

define_mes_anterior() {
  mes=`date +%m`
  mes=$(expr $mes - 1)
  if [ $mes = 0 ]; then
    ano=`date +%Y`
    ano=$(expr $ano - 1)
    mes=${ano}-12
  else
    mes=`date +%Y`-$mes
  fi
}

move_logs() {
  echo "Logs: Movendo logs em adump para adump/old/${ORACLE_SID}_audit_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/adump
  touch ${ORACLE_SID}_audit_${mes}.tar $log 2>> $log
  find -name "ora_*.aud" -exec tar -rf ${ORACLE_SID}_audit_${mes}.tar {} ; 2>> $log
  if [ -s ${ORACLE_SID}_audit_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_audit_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_audit_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ora_*.aud
  else
    rm ${ORACLE_SID}_audit_${mes}.tar  >> $log 2>> $log
  fi

  echo "Logs: Movendo logs em bdump para bdump/old/${ORACLE_SID}_bdump_log_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/bdump
  touch ${ORACLE_SID}_bdump_log_${mes}.tar $log 2>> $log
  find -name "${ORACLE_SID}_${mes}-*.log" -exec
    tar -rf ${ORACLE_SID}_bdump_log_${mes}.tar {} ; 2>> $log
  if [ -s ${ORACLE_SID}_bdump_log_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_bdump_log_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_bdump_log_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_${mes}-*.log
  else
    rm ${ORACLE_SID}_bdump_log_${mes}.tar >> $log 2>> $log
  fi

  echo "Logs: Movendo trace em bdump para bdump/old/${ORACLE_SID}_bdump_trace_${mes}.tar.bz2"` >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/bdump
  touch ${ORACLE_SID}_bdump_trace_${mes}.tar $log 2>> $log
  find -name "${ORACLE_SID}_*.trc" -exec tar -rf ${ORACLE_SID}_bdump_trace_${mes}.tar {} ; 2>> $log
  if [ -s ${ORACLE_SID}_bdump_trace_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_bdump_trace_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_bdump_trace_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_*.trc
  else
    rm ${ORACLE_SID}_bdump_trace_${mes}.tar >> $log 2>> $log
  fi

  echo "Logs: Movendo trace em cdump para cdump/old/${ORACLE_SID}_cdump_trace_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/cdump
  touch ${ORACLE_SID}_cdump_trace_${mes}.tar $log 2>> $log
  find -name "core_*" -exec tar -rf ${ORACLE_SID}_cdump_trace_${mes}.tar {} ; 2>> $log
  if [ -s ${ORACLE_SID}_cdump_trace_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_cdump_trace_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_cdump_trace_${mes}.tar.bz2 old  >> $log 2>> $log
    rm -R core_*
  else
    rm ${ORACLE_SID}_cdump_trace_${mes}.tar >> $log 2>> $log
  fi

  echo "Logs: Movendo trace em udump para udump/old/${ORACLE_SID}_udump_trace_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/udump
  touch ${ORACLE_SID}_udump_trace_${mes}.tar $log 2>> $log
  find -name "${ORACLE_SID}_*.trc" -exec tar -rf ${ORACLE_SID}_udump_trace_${mes}.tar {} ; 2>> $log
  if [ -s ${ORACLE_SID}_udump_trace_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_udump_trace_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_udump_trace_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_*.trc
  else
    rm ${ORACLE_SID}_udump_trace_${mes}.tar >> $log
  fi

  echo "Logs: Movendo logs de backup para backup/old/${ORACLE_SID}_backup_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/backup
  touch ${ORACLE_SID}_udump_trace_${mes}.tar $log 2>> $log
  find -name "*_${mes}.log" -exec tar -rf ${ORACLE_SID}_backup_log_${mes}.tar {} ; 2>> $log
  if [ -s ${ORACLE_SID}_backup_log_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_backup_log_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_backup_log_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_${mes}-*.log
  else
    rm ${ORACLE_SID}_backup_log_${mes}.tar >> $log 2>> $log
  fi
}

#Rotina principal
case $operation in
  'copia_archives')
    copia_archives
    verifica_discos
  ;;
  'backup_noturno')
    echo "" >> $log 2>> $log
    echo "Inicio da rotina de backup noturno em $ORACLE_SID em "`uname -n`" para o dia ${dia}" >> $log
    echo "================================================================="  >> $log
    echo "" >> $log
    analize
    backup_logico
    verifica_data_file
    backup_fisico_on_line
    compara_backup_fisico
    backup_control_file
    backup_dbs
    limpa_archives
    verifica_alert
    verifica_tablespaces
    mostra_espaco_disco
    echo "Fim do backup noturno. Este log está disponível em $log" >> $log
    cat $log | mail -s "Log do backup noturno de `uname -n`/${dia}" $oracle_mail
  ;;
  'backup_off_line')
    echo "" >> $log
    echo "Início do backup off line de $ORACLE_SID em "`uname -n`" para o dia ${dia}" >> $log
    echo "=============================================================================="  >> $log
    echo "" >> $log
    shut_down
    copia_datafiles
    start_up
    echo "Fim do backup off line. Este log está disponível em $log" >> $log
    cat $log | mail -s "Log do backup off line de `uname -n`/${dia}" $oracle_mail
  ;;
  'rotina_mensal')
    define_mes_anterior
    echo "" >> $log
    echo "Início da rotina mensal de $ORACLE_SID em "`uname -n`" para o mês ${mes} em ${dia}" >> $log
    echo "=============================================================================="  >> $log
    echo "" >> $log
    move_logs
    verifica_espaco_disco
    echo "Fim da rotina mensal. Este log está disponível em $log" >> $log
    cat $log | mail -s "Log da rotina mensal de `uname -n`/${dia}" $oracle_mail
  ;;
  *)
    echo "***** A operação ${operation} não é válida" >> $log
    echo "***** chamada $0 $* ilegal"
    echo "***** uso: $0  " >> $log
  ;;
esac

Referências

6 respostas

  1. É importante termos matérias com o objetivo de realizar as tarefas “junto as explicações”, conforme visto nesta matéria.

    Muitos DBA´s não costumam perguntar e nem mesmo compartilhar as experiências (talvez por vergonha ou sei lá).

    Em algumas empresas, o DBA é um cara “solitário” e não tem outro colega de trabalho para conversar sobre os problemas encontrados e soluções adotadas.

    Esta matéria parece muito interessante. Vou experimentar.

    Parabéns pela iniciativa.

  2. Excelente scripts, muito completo e muito bem explicado cada linha dos comandos.
    Parabéns!

Deixe uma resposta