Backup Linux, MySQL Parte 1

Os backups são uma parte importante da administração de qualquer servidor.

Por mais confiável que seja a máquina, desastres acontecem, sem falar na possibilidade de erro humano. Sem backups regulares, é apenas questão de tempo até que você tenha problemas e perca dados importantes.

Os backups são uma parte importante da administração de qualquer servidor. Diferente de um desktop, onde você pode simplesmente fazer uma imagem do HD usando o partimage ou outro programa similar, em uma servidor os backups precisam, quase sempre, serem feitos com o servidor em operação, sem atrapalharem o acesso dos usuários. O nível de dificuldade também é um pouco maior, já que além de arquivos e pastas, é necessário salvar também arquivos de configuração, bases de dados do MySQL e assim por diante.
Por mais confiável que seja a máquina, desastres acontecem, sem falar na possibilidade de erro humano. Sem backups regulares, é apenas questão de tempo até que você tenha problemas e perca dados importantes.

Em resumo, as principais pastas com as quais você precisa se preocupar ao fazer backup do servidor são:

/var/www: Em um servidor web, a pasta com as páginas é sempre o diretório mais importante, já que é nele que ficarão a maior parte dos arquivos dos usuários.

/var/lib/mysql: Este é o diretório padrão das bases de dados do MySQL, que em muitos casos são tão ou mais importantes que as pastas dos sites propriamente ditos. Embora seja associado ao uso em servidores web, o MySQL pode ser usado para os mais diversos tipos de tarefas.

/home: Se você configurou os virtual hosts do Apache para utilizarem pastas dentro dos diretórios home dos usuários, a pasta home assume o posto de diretório essencial, no lugar da pasta /var/www. O home também é importante caso seja usado para armazenar o spool de e-mails, no caso de servidores de arquivos ou em servidores de acesso remoto (como no caso do LTSP).

/etc: É importante que você faça também backup das configurações do servidor, concentradas na pasta “/etc”, caso contrário, você vai passar maus bocados tentando se lembrar das configurações, contas de usuários e outras informações ao reconfigurar o servidor após algum desastre. 🙂

/var/log: Os logs do sistema também são importantes. Em muitos casos existem normas administrativas ou até mesmo normas legais que tornam obrigatório manter os logs de acesso por longos períodos, daí a necessidade de incluí-los no backup.

Além dos diretórios de dados do sistema, é importante que você tome nota de todas as partições montadas em diretórios fora das pastas principais do sistema que sejam usadas para armazenar arquivos, além de outras pastas que você utilize para guardar dados ou configurações.

Depois de definidos os diretórios a incluir no backup, falta definir que tipo de mídia utilizar.

Antigamente, as unidades de fita eram as mais utilizadas para backup de grandes volumes de dados. As principais vantagens das unidades de fita eram a grande capacidade, combinada com a boa confiabilidade e um custo por megabyte relativamente baixo. Temos aqui uma IBM 7329 SLR100, uma unidade SCSI antiga, que utiliza fitas de 50 GB, com um carregador automático com capacidade para 8 fitas, totalizando 400 GB. O “100” no nome indica a capacidade estimada levando em conta um fator de compressão de 2:1, que dependia dos tipos de arquivos incluídos no backup e que, naturalmente, nem sempre era atingido:

Utilitários como o tar foram originalmente desenvolvidos para facilitarem os backups em fita, gerando um único arquivo contendo todos os dados, que era então gravado na fita de forma sequencial. Para salvar um backup da pasta “/var/www” em uma unidade de fita detectada pelo sistema como “/dev/st0”, apenas empacotando os arquivos (sem comprimir), você usaria o comando:

# tar -cvf /dev/st0 /var/www

Isso seria prático enquanto você pudesse armazenar os backups diários em uma única fita, ou caso você utilizasse uma unidade com um carregador automático. É possível dividir o backup em vários volumes e salvá-lo em fitas separadas, mas isso torna o processo extremamente imprático, sem falar que os custos se multiplicam junto com o número de fitas necessárias.

Hoje em dia, existem unidades de fita com mídias de até 800 GB reais (ou 1.6 TB comprimidos), como a Tandberg LTO-4 FH (que custa, em julho de 2008, nada menos do que US$ 4500, mais o custo das fitas), entretanto, elas são bastante caras, o que torna os HDs uma opção muito mais atrativa, já que já existem no mercado HDs de 1 TB a preços competitivos.

Surge então a figura do NAS, um servidor de arquivos dedicado, que freqüentemente utiliza vários HDs em RAID de forma a obter a capacidade necessária. Além das inúmeras opções de produtos comerciais, você pode montar seu próprio NAS usando um PC com Linux. Ao utilizar um NAS, ou outro tipo de servidor de armazenamento, os backups tornam-se mais simples, pois podem ser feitos via rede. Com isso, todo o trabalho manual de trocar as fitas de armazenamento, ou plugar e desplugar HDs externos é eliminado e os backups podem se tornar um processo inteiramente automatizado.

Existem também os casos em que o volume de dados a armazenar é pequeno, o que torna viável utilizar DVDs ou mesmo CD-ROMs para realizar os backups. A vantagem nesse caso é que as mídias são baratas e você pode simplesmente queimar uma nova mídia a cada backup, armazenando todas as cópias antigas. Os CDs e DVDs possuem também uma boa longevidade; mídias de boa qualidade, armazenadas em um ambiente sem luz e com baixa umidade duram cerca de 20 anos ou, em muitos casos, até mais.

Durante a década de 70, vários utilitários foram desenvolvidos para fazer backup de arquivos armazenados em servidores Linux. Os computadores da época eram muito limitados, por isso os utilitários precisavam ser simples e eficientes, e deveriam existir meios de agendar os backups para horários de pouco uso das máquinas.

Sugiram então utilitários como o tar e o gzip e, mais tarde, ferramentas como o rsync. Estes utilitários eram tão eficientes que continuaram sendo usados ao longo do tempo e, por incrível que possa parecer, são usados sem grandes modificações até os dias hoje.

Naturalmente, existem muitos utilitários amigáveis de backup, como o Amanda (http://sourceforge.net/projects/amanda/), mas, internamente, eles continuam utilizando como base o o dump, tar, gzip e outros trigenários. Mais incrível ainda é que estes utilitários possuem uma base de usuários relativamente pequena. A maior parte dos backups ainda é feita através de scripts personalizados, escritos pelo próprio administrador. E, novamente, estes scripts utilizam o tar, gzip, rsync e outros. Vamos começar com alguns exemplos simples:

Para compactar o conteúdo de uma pasta, usamos o tar combinado com o gzip ou o bzip2. O tar agrupa os arquivos e o gzip/bzip2 os compacta. Os arquivos compactados com o gzip usam por padrão a extensão “tar.gz”, enquanto os compactados com o bzip2 usam a extensão “tar.bz2”. O bzip2 é mais eficiente (chega a obter 10% ou mais de compressão adicional) mas em compensação é bem mais pesado: demora cerca de 3 vezes mais para compactar os mesmos arquivos. Você escolhe entre um e outro de acordo com a tarefa.

O comando para compactar uma pasta é similar ao “tar -zxvf” que usamos para descompactar arquivos. Para compactar a pasta “arquivos/”, criando o arquivo “arquivos.tar.gz”, o comando seria:

$ tar -zcvf arquivos.tar.gz arquivos/

O “c” indica que o tar deve criar um novo arquivo e o “v” faz com que exiba informações na tela enquanto trabalha. Se preferir comprimir em bz2, muda apenas a primeira letra; ao invés de “z” usamos “j”:

$ tar -jcvf arquivos.tar.bz2 arquivos/

Para descompactar o arquivo posteriormente, trocamos a opção “c” por “x”, como em:

$ tar -jxvf arquivos.tar.bz2

Como não indicamos uma pasta de destino, o arquivo será simplesmente descompactado na pasta atual. Se o arquivo não é muito grande ou se o espaço em disco não é problema, você pode simplesmente descompactar o arquivo dentro da sua pasta home, ou em outro diretório com espaço suficiente disponível e copiar manualmente os arquivos desejados para a pasta de destino. Essa acaba sendo a opção mais segura, já que você tem mais tempo para revisar tudo e ter certeza de que não está substituindo arquivos por versões antigas.

Você pode também descompactar o arquivo diretamente na pasta desejada. Imagine que você fez anteriormente o backup da pasta “/var/www/site”, gerando o arquivo “site.tar.gz”, usando os comandos:

# cd /var/www
# tar -zcvf /mnt/sdb1/backups/site.tar.gz site

Nesse caso, o arquivo contém a pasta “site/” e todo o seu conteúdo. Para restaurá-lo posteriormente, diretamente no destino, você usaria:

# cd /var/www
# tar -zxvf /mnt/sdb1/backups/site.tar.gz

Como o comando é executado diretamente dentro da pasta “/var/www/”, os arquivos são restaurados diretamente na pasta “site”. Usado desta forma, o tar subscreve os arquivos da pasta de destino sem pedir confirmação, por isso tenha cautela ao usá-lo. É muito fácil errar o diretório e restaurar os arquivos na pasta errada, ou especificar o arquivo incorreto e subscrever o conteúdo da pasta pelo de um backup antigo.

Continuando, um dos grandes problemas em utilizar arquivos compactados é que é muito difícil recuperar o conteúdo do arquivo caso ele seja corrompido por qualquer motivo (um badblock no HD, ou um erro durante a transferência, por exemplo). Diferente de em uma pasta com diversos arquivos, onde um ou mais badblocks apenas fariam com que alguns dos arquivos ficassem danificados, erros em um arquivo compactado podem comprometer todo o seu conteúdo.

Tendo isso em mente, é saudável verificar os backups depois de copiá-los para a mídia de destino, o que pode ser feito usando o próprio tar. Nesse caso, usamos a opção “-tf”, que faz com que ele liste o conteúdo do arquivo, como em:

$ tar -tf arquivos.tar.bz2

Isso obrigará o tar a abrir o arquivo e listar seu conteúdo. Se houver qualquer erro durante o processo, ele exibirá uma mensagem de erro, alertando sobre o problema.

Estes comandos seriam ideais para fazer um backup completo de uma ou várias pastas do sistema, gerando um arquivo compactado que poderia ser armazenado num HD externo, gravado em um DVD ou mesmo transferido via rede para outro servidor.

Imagine agora um outro cenário, onde você precisa fazer backup dos arquivos de uma pasta de trabalho diariamente. Os arquivos gerados não são muito grandes e você tem muito espaço disponível, mas é necessário que os backups diários sejam feitos em arquivos separados e sejam guardados por um certo período, de forma que seja possível recuperar um arquivo qualquer a partir do backup feito em uma determinada data.

Ao invés de ficar renomeando os arquivos, você poderia usar um pequeno script para que os arquivos fossem gerados já com a data e hora incluída no nome do arquivo:

DATA=`date +%Y-%m-%d-%H.%M`
cd /mnt/backup
tar -zcvf trabalho-“$DATA”.tar.gz /mnt/hda6/trabalho/

A primeira linha do script cria uma variável “DATA”, contendo o resultado do comando “date +%Y-%m-%d-%H.%M.%S” (os caracteres “`” usados no comando são crases). O comando date retorna a data e hora atual, como em “Qua Jul 2 10:23:46 BRT 2008”. A saída padrão não é muito adequada para usar em nomes de arquivos, por isso usamos as opções para alterar o formato de saída, de modo que o resultado seja “2008-07-02-10.23” (ano, mês, dia, hora, minuto). Usamos este valor no nome do arquivo com o backup, de forma que, cada vez que você chame o script, seja gerado um arquivo com a data e hora em que foi gerado.

O próximo passo é fazer com que este script de backup seja executado diariamente, de forma automática, o que pode ser feito usando o cron, que apresentei na dica anterior: http://www.guiadohardware.net/dicas/cron.html

Em primeiro lugar, salve os comandos em um arquivo de texto, que vamos chamar de “script-backup” e transforme-o em executável:

# chmod +x script-backup

Para que o script seja executado automaticamente todos os dias, edite o arquivo “/etc/crontab” adicionando uma nova linha, especificando o horário em que o script será executado, o login sob o qual ele será executado (para simplificar as coisas, você pode utilizar o próprio root) e a localização do script, como em:

25 6 * * * root /usr/local/bin/script-backup

O “25 6” indica o minuto e a hora. Se quiser que o script seja executado às 11 da noite, por exemplo, mude para “00 23”. As alterações feitas no arquivo são lidas automaticamente pelo cron, de forma que não é necessário reiniciar o serviço. Se quiser verificar se o cron está mesmo ativo, use o comando “ps aux | grep cron”, que deverá retornar algo similar a: “root 2002 0.0 0.1 2280 848 ? Ss Jun30 0:00 /usr/sbin/cron”.

Nesse primeiro exemplo, usei a pasta “/mnt/backup” para salvar os arquivos. Esta pasta pode ser o ponto de montagem de um HD externo ou de um compartilhamento de rede, por exemplo. O seu script pode conter os comandos necessários para montar e desmontar a partição automaticamente, além de executar operações diversas definidas por você.

Imagine, por exemplo, que o backup é sempre feito na primeira partição de um HD externo, ligado na porta USB, que é sempre detectada pelo sistema como “/dev/sda1”. O script deve ser capaz de montar a partição, gravar o arquivo de backup e depois desmontá-la. Se, por acaso, o HD não estiver plugado, o script deve abortar o procedimento.

Para isso, precisamos verificar se o HD realmente foi montado depois de executar o comando “mount /dev/sda1 /mnt/sda1”. Existem muitas formas de fazer isso, uma das mais simples é filtrar a saída do comando “mount” (que mostra todos os dispositivos montados) usando o grep para ver se o “/mnt/sda1” aparece na lista. Se não estiver, o script termina, caso esteja, ele continua, executando os comandos de backup:

mount /dev/sda1 /mnt/backup
montado=`mount | grep /mnt/backup`

if [ -z “$montado” ]; then
exit 2
else
DATA=`date +%Y-%m-%d-%H.%M`
cd /mnt/backup
tar -zcvf trabalho-“$DATA”.tar.gz /mnt/hda6/trabalho/
umount /mnt/sda1
fi

Uma vez que o cron fosse configurado para executar o script diariamente, o backup passaria a ser feito automaticamente sempre que você deixasse o HD externo plugado no final do expediente. Se esquecer de plugar o HD em algum dia, o script percebe que a partição não foi montada e não faz nada.

Se preferir que o script grave o backup em um DVD, ao invés de simplesmente salvar em uma pasta, você pode usar o “growisofs” para gravá-lo na mídia. Neste caso, vamos gerar o arquivo em uma pasta temporária e deletá-lo depois da gravação:

DATA=`date +%Y-%m-%d-%H.%M`

# Sanity-check para ter certeza de que tudo está em ordem:
rm -rf /tmp/backup; mkdir /tmp/backup; cd /tmp/backup

# Gera o arquivo, grava o DVD e deleta a pasta temporária
tar -zcvf trabalho-“$DATA”.tar.gz /mnt/hda6/trabalho/
growisofs -speed=2 -Z /dev/dvd -R -J /tmp/backup/trabalho-“$DATA”.tar.gz
cd ../; rm -rf /tmp/backup

O “-speed=2” permite que você especifique a velocidade de gravação do DVD, enquanto o “-Z” cria uma nova seção dentro da mídia. É possível usar o mesmo disco para gravar vários backups (se o espaço permitir) adicionando a opção “-M” (logo depois do “-Z”, dentro do comando) a partir da segunda gravação, que adiciona novas seções no DVD, até que o espaço se acabe.

O “/dev/dvd” indica o dispositivo do drive de DVD. A maioria das distribuições cria o link /dev/dvd apontando para o dispositivo correto, mas, em caso de problemas, você pode indicar diretamente o dispositivo correto, como, por exemplo, “/dev/hdc”. As opções “-R -J” adicionam suporte às extensões RockRidge e Joilet, que oferecem (respectivamente) suporte a nomes de arquivos com mais de 8 caracteres no Linux e no Windows.

Se o cron for configurado para executar o script todos os dias, você só precisará se preocupar em deixar o DVD no drive antes de sair. Se quiser que ele faça graça, ejetando a mídia depois de terminar a gravação, adicione um “eject /dev/dvd” no final do script.

Se preferir fazer os backups em CDR, crie uma imagem ISO usando o mkisofs e em seguida grave-a no CD usando o cdrecord. Nesse caso, o comando do growisofs dentro do script seria substituído por:

mkisofs -r -J -o trabalho.iso /tmp/backup/trabalho-“$DATA”.tar.gz
cdrecord dev=/dev/hdc trabalho.iso

Este comando do cdrecord funciona em distribuições recentes, que utilizam o Kernel 2.6 em diante (com o módulo ide-cd). No Kernel 2.4, era usada emulação SCSI para acessar o gravador de CD, fazendo com que ele fosse visto e acessado pelo sistema como se fosse um gravador SCSI. Nesse caso, o comando de gravação seria “cdrecord dev=0,0,0 -data arquivo.iso”, onde o “0,0,0” é o dispositivo do gravador, que você descobriria usando o comando “cdrecord -scanbus”.

Outra pequena observação é que nas distribuições derivadas do Debian o cdrecord é substituído pelo wodim, um fork do projeto que desempenha a mesma função. Nelas, você recebe um “bash: cdrecord: command not found” ao executar o comando, já que o nome do arquivo é diferente. Você pode resolver o problema de forma simples criando um link:

# ln -s /usr/bin/wodim /usr/bin/cdrecord

Outra boa opção seria salvar os backups em um servidor externo, de preferência um servidor remoto, situado em outro estado ou em outro país. Usar dois servidores em locais diferentes elimina a possibilidade de algum tipo de desastre (como um incêndio ou uma inundação) destruir tanto o servidor quanto os backups.

Uma forma simples de fazer com que o script consiga transferir os arquivos automaticamente no final do processo é utilizar um par de chaves do SSH sem passphrase, o que permite que o script transfira arquivos usando o comando “scp”, sem precisar lhe pedir a senha ou a passphrase de acesso ao realizar cada cópia. Essa opção é um pouco menos segura do que usar chaves protegidas por uma passphrase, já que caso alguém consiga obter acesso ao arquivo “.ssh/id_rsa” dentro no home do usuário, poderá obter acesso ao servidor. Entretanto, em muitas situações este é um risco aceitável, principalmente se o backup é feito diretamente entre dois servidores protegidos. Além do mais, o risco é reduzido caso você utilize uma conta limitada no segundo servidor.

O primeiro passo seria criar um usuário no segundo servidor, que será usado para permitir o acesso do script. Aproveite para já ajustar o diretório home, especificando a pasta que será usada para armazenar os backups, como em:

# adduser –home /mnt/sdb1/backups bkuser

Em seguida, criamos o par de chaves que será usado para o acesso no primeiro servidor usando o comando “ssh-keygen -t rsa”. Ele deve ser executado usando o usuário que será usado para executar o script de backup. Se ele for ser executado pelo root, então o comando é também executado como root:

# ssh-keygen -t rsa

Como a idéia é criar uma chave que possa ser usada para login automático, simplesmente pressione Enter quando o ssh-keygen perguntar pela passphrase, deixando-a em branco.

O próximo passo é instalar a chave gerada no segundo servidor (o “backup.gdhn.com.br” no exemplo), usando o comando “ssh-copy-id”, especificando o usuário criado no passo anterior e o endereço do segundo servidor, como em:

# ssh-copy-id -i ~/.ssh/id_rsa.pub bkuser@backup.gdhn.com.br

Com isso, o primeiro servidor passa a ter acesso direto ao segundo através do usuário “bkuser” (especificado no comando), que usaremos para transferir os arquivos através do scp. Você pode fazer um teste transferindo um arquivo qualquer do primeiro servidor para o segundo, como em:

# scp arquivo.tar.gz bkuser@backup.gdhn.com.br:/mnt/sdb1/backups/

Você perceberá que o comando será executado diretamente, sem pedir senha. O próximo passo é adicionar o comando para transferir o arquivo no seu script de backup, como neste exemplo:

#!/bin/sh

DATA=`date +%Y-%m-%d-%H.%M`
cd /mnt/backup
tar -zcvf www-$DATA.tar.gz /var/www

scp www-$DATA.tar.gz bkuser@backup.gdhn.com.br:/mnt/sdb1/backups/
rm -f www-$DATA.tar.gz

Com isso, o script gera o arquivo com o backup, copia para o segundo servidor via scp e, depois de concluída a transferência, deleta a cópia local do arquivo, de forma que elas não se acumulem até acabar com o espaço em disco.

O passo final seria automatizar a execução do script, adicionando uma entrada no arquivo “/etc/crontab” (do primeiro servidor), como em:

59 4 * * * root /usr/local/bin/script-backup

Esta entrada faria com que o script fosse executado todos os dias às 4:59 da manhã, sempre gerando um novo arquivo com a data de quando foi executado e copiando-o para o segundo servidor, onde os backups ficarão arquivados.

Texto autoria: Carlos E. Morimoto.

Backup Linux, MySQL Parte 2