Script de backup
LidoNesta aula, você aprenderá a criar scripts de backup robustos em Bash, cobrindo estratégias de backup, uso do tar com compressão, rotação de backups e agendamento com cron. Ao final, terá conhecimento prático para automatizar backups de forma segura e eficiente.
Backup é uma das tarefas mais críticas na administração de sistemas. Nesta aula, vamos explorar como criar scripts de backup eficientes em Bash, desde a estratégia até a automação. Você aprenderá a utilizar ferramentas como tar, gzip, bzip2 e xz, além de implementar rotação de arquivos e agendar execuções com cron.
Um bom script de backup deve ser confiável, automatizável e fácil de manter. Vamos abordar cada aspecto com exemplos práticos, garantindo que você possa adaptar os scripts para suas necessidades.
Estratégia
Antes de escrever qualquer script, é essencial definir uma estratégia de backup. Isso envolve decidir o que será copiado, com que frequência, onde os backups serão armazenados e por quanto tempo. Uma estratégia comum é o esquema 3-2-1: 3 cópias dos dados, em 2 mídias diferentes, com 1 cópia fora do local. No contexto de scripts, podemos implementar backups completos, incrementais ou diferenciais.
Backups completos copiam todos os dados selecionados, são simples mas consomem espaço e tempo. Incrementais copiam apenas as alterações desde o último backup (completo ou incremental), enquanto diferenciais copiam as alterações desde o último backup completo. Em scripts, podemos usar ferramentas como rsync ou tar com opções específicas. Para esta aula, focaremos em backups completos com tar, que é uma ferramenta clássica e poderosa.
#!/bin/bash
# Script para backup completo de diretórios importantes
SOURCE_DIRS="/etc /home /var/www"
BACKUP_DIR="/backup"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
FILENAME="backup_${DATE}.tar.gz"
tar -czf "${BACKUP_DIR}/${FILENAME}" $SOURCE_DIRS
echo "Backup completo criado: ${BACKUP_DIR}/${FILENAME}"
Este script define os diretórios de origem, o diretório de destino, gera um nome de arquivo com data e hora, e usa tar para criar um arquivo compactado. Note que usamos a opção -c (create), -z (gzip), -f (file).
tar e compressão
O comando tar é a ferramenta padrão para arquivar arquivos em Unix/Linux. Ele pode ser combinado com algoritmos de compressão para reduzir o tamanho dos arquivos. As opções mais comuns são -z (gzip), -j (bzip2), -J (xz). Cada um tem trade-offs entre velocidade e taxa de compressão. Para backups, gzip é rápido e amplamente suportado; bzip2 e xz oferecem melhor compressão mas são mais lentos.
Além de criar arquivos, tar pode listar, extrair e atualizar. Em scripts, é importante verificar se o backup foi criado corretamente. Podemos usar a opção -t para testar a integridade, ou verificar o código de saída ($?). Também podemos usar o comando du para verificar o tamanho do arquivo criado.
#!/bin/bash
# Script com verificação de integridade
SOURCE="/home/user/documentos"
BACKUP_DIR="/backup"
DATE=$(date +%Y-%m-%d)
FILENAME="documents_${DATE}.tar.xz"
# Criar backup com compressão xz
tar -cJf "${BACKUP_DIR}/${FILENAME}" "$SOURCE"
# Verificar se o comando foi bem-sucedido
if [ $? -eq 0 ]; then
echo "Backup criado com sucesso: ${BACKUP_DIR}/${FILENAME}"
# Listar conteúdo para confirmar
tar -tJf "${BACKUP_DIR}/${FILENAME}" | head
else
echo "Erro ao criar backup" >&2
exit 1
fi
Aqui usamos -J para xz e depois testamos com -tJf. Essa verificação é crucial para garantir que o backup não está corrompido.
Rotação
Manter backups antigos pode encher o disco rapidamente. A rotação de backups é a política de remover backups antigos para liberar espaço. Podemos implementar rotação por número de arquivos ou por idade. Por exemplo, manter apenas os últimos 7 backups diários, ou excluir backups com mais de 30 dias.
No Bash, podemos usar o comando find para localizar arquivos antigos e removê-los. É importante ter cuidado com a remoção, então vamos incluir uma verificação. Uma estratégia comum é manter backups diários por uma semana, semanais por um mês, e mensais por um ano.
#!/bin/bash
# Rotação: manter apenas os últimos 5 backups
BACKUP_DIR="/backup"
KEEP=5
# Listar backups por ordem de criação (mais recentes primeiro)
# e remover os excedentes
cd "$BACKUP_DIR" || exit 1
ls -1t backup_*.tar.gz | tail -n +$((KEEP+1)) | while read file; do
echo "Removendo backup antigo: $file"
rm "$file"
done
Este script lista os arquivos que correspondem ao padrão, ordena por tempo (mais recentes primeiro), e remove os que estão além do quinto. Também podemos usar find com -mtime para remover por idade.
# Remover backups com mais de 30 dias
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +30 -delete
Agendamento
Para automatizar backups, usamos o cron, um agendador de tarefas do Unix. O cron lê um arquivo crontab com linhas que especificam quando executar comandos. Cada linha tem cinco campos: minuto, hora, dia do mês, mês e dia da semana. Por exemplo, para executar um backup todos os dias às 2h da manhã, adicionamos a linha: 0 2 * * * /caminho/para/backup.sh.
É importante garantir que o script tenha permissão de execução e que o ambiente esteja configurado corretamente (variáveis PATH, etc.). Podemos também usar o sistema de logs para monitorar a execução. Vamos criar um script completo que combina backup e rotação, e agendá-lo no cron.
#!/bin/bash
# Script completo: backup + rotação
set -euo pipefail
SOURCE_DIRS="/etc /home"
BACKUP_DIR="/backup"
KEEP=7
DATE=$(date +%Y-%m-%d_%H-%M-%S)
FILENAME="backup_${DATE}.tar.gz"
# Criar backup
tar -czf "${BACKUP_DIR}/${FILENAME}" $SOURCE_DIRS
# Verificar integridade
if ! tar -tzf "${BACKUP_DIR}/${FILENAME}" > /dev/null; then
echo "Falha na verificação do backup" >&2
exit 1
fi
# Rotação: manter apenas os últimos KEEP backups
ls -1t "${BACKUP_DIR}"/backup_*.tar.gz | tail -n +$((KEEP+1)) | while read old_file; do
echo "Removendo backup antigo: $old_file"
rm "$old_file"
done
echo "Backup concluído: ${BACKUP_DIR}/${FILENAME}"
Para agendar, editamos o crontab com crontab -e e adicionamos:
# Backup diário às 2h
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Redirecionamos a saída para um log para monitoramento. Lembre-se de tornar o script executável com chmod +x.
Boas práticas
- Sempre testar o script manualmente antes de agendar.
- Usar caminhos absolutos no script e no cron.
- Incluir tratamento de erros e logs.
- Proteger o diretório de backup com permissões adequadas.
- Considerar criptografia para dados sensíveis.
Referências
- Manual do GNU tar
- Página de manual do cron
- Formato do crontab
- Manual do gzip
- Site oficial do xz
- Manual do find
Exercícios
- Escreva um script que crie um backup compactado com bzip2 de um diretório de sua escolha e verifique a integridade.
- Implemente uma rotação que mantenha apenas os últimos 3 backups, usando o comando find com -mtime para remover arquivos com mais de 3 dias.
- Crie um script que faça backup de múltiplos diretórios e envie um e-mail de notificação (simule com echo).
- Agende o script do exercício 1 para rodar todos os dias às 3:30 da manhã, usando cron, e explique como testar.
- Modifique o script completo para usar compressão xz e ajuste a rotação para manter 10 backups. Teste o script e verifique se a rotação funciona.
#!/bin/bash
SOURCE="/home/user/docs"
BACKUP_DIR="/backup"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
FILENAME="docs_${DATE}.tar.bz2"
tar -cjf "${BACKUP_DIR}/${FILENAME}" "$SOURCE"
if tar -tjf "${BACKUP_DIR}/${FILENAME}" > /dev/null; then
echo "Backup OK: ${BACKUP_DIR}/${FILENAME}"
else
echo "Backup corrompido" >&2
exit 1
fi
#!/bin/bash
BACKUP_DIR="/backup"
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +3 -delete
#!/bin/bash
DIRS="/etc /home"
DEST="/backup"
DATE=$(date +%Y-%m-%d)
FILE="multi_${DATE}.tar.gz"
tar -czf "${DEST}/${FILE}" $DIRS && echo "Backup criado: ${DEST}/${FILE}"
# Simulação de envio de e-mail
echo "Backup concluído em $(date)" | mail -s "Backup diário" admin@example.com
30 3 * * * /caminho/para/script.sh ao crontab com crontab -e. Para testar, execute o script manualmente e verifique se o backup é criado. Depois, use crontab -l para confirmar a linha.#!/bin/bash
set -euo pipefail
SOURCE_DIRS="/etc /home"
BACKUP_DIR="/backup"
KEEP=10
DATE=$(date +%Y-%m-%d_%H-%M-%S)
FILENAME="backup_${DATE}.tar.xz"
tar -cJf "${BACKUP_DIR}/${FILENAME}" $SOURCE_DIRS
if ! tar -tJf "${BACKUP_DIR}/${FILENAME}" > /dev/null; then
echo "Erro na verificação" >&2
exit 1
fi
ls -1t "${BACKUP_DIR}"/backup_*.tar.xz | tail -n +$((KEEP+1)) | while read old; do
rm "$old"
done
echo "Backup OK: ${BACKUP_DIR}/${FILENAME}"