O ZFS oferece uma solução poderosa para backups confiáveis em sistemas Linux, especialmente por meio dos comandos zfs send e zfs receive. Essas ferramentas permitem transferir dados de snapshots entre pools ZFS, seja para um disco de backup local ou um servidor remoto, garantindo integridade e eficiência.
Como Funciona o zfs send e zfs receive
O zfs send serializa um snapshot (ou a diferença incremental entre dois snapshots) em um fluxo de bytes, enquanto o zfs receive aplica esse fluxo em um conjunto de dados de destino. O resultado é uma réplica exata do snapshot original.
Vantagens em relação a ferramentas genéricas de cópia de arquivos:
- Transferência incremental: Apenas blocos modificados são enviados.
- Eficiência: Dados comprimidos são transferidos já compactados.
- Preservação de metadados: Permissões, propriedades e timestamps são mantidos.
Pré-requisitos
Antes de começar, certifique-se de que:
- O ZFS está instalado em ambas as máquinas (
sudo apt install zfsutils-linux). - O SSH está configurado para autenticação por chave (caso use replicação remota).
- O pool de destino já existe.
Replicação Inicial (Full Send)
Backup Local
# Crie um snapshot para enviar
sudo zfs snapshot reservatorio/web@2026-03-02
# Envie para um destino local
sudo zfs send reservatorio/web@2026-03-02 | sudo zfs receive -F backup_pool/web
- A flag
-Fforça a atualização, descartando qualquer conteúdo existente no destino.
Backup Remoto via SSH
# Envie para um servidor remoto
sudo zfs send reservatorio/web@2026-03-02 | \
ssh servidor-backup.example.com "sudo zfs receive -F backup_pool/web"
Dica: Configure o sudoers no servidor remoto para permitir zfs receive sem senha ou execute como root via SSH.
Monitorando o Progresso
Use o mbuffer para visualizar o progresso da transferência:
sudo apt install mbuffer
sudo zfs send reservatorio/web@2026-03-02 | \
mbuffer -s 128k -m 1G | \
ssh servidor-backup.example.com "sudo zfs receive backup_pool/web"
O mbuffer exibirá informações como:
textCopiar8.50 GiB [ 45.2 MiB/s] em 3:14
Replicação Incremental: Atualizações Eficientes
Após a replicação inicial, use sends incrementais para transferir apenas os dados modificados:
# Envie apenas as diferenças entre dois snapshots
sudo zfs send -i reservatorio/web@2026-03-01 reservatorio/web@2026-03-02 | \
ssh servidor-backup.example.com "sudo zfs receive backup_pool/web"
- A flag
-iindica que a transferência é incremental, enviando apenas blocos alterados.
Verifique os snapshots no destino:
ssh servidor-backup.example.com "sudo zfs list -t snapshot backup_pool/web"
Replicação Recursiva
Para replicar uma hierarquia completa de datasets:
# Crie um snapshot recursivo
sudo zfs snapshot -r reservatorio/bancos@2026-03-02
# Envie recursivamente
sudo zfs send -R reservatorio/bancos@2026-03-02 | \
ssh servidor-backup.example.com "sudo zfs receive -F backup_pool/bancos"
- A flag
-Rreplica todos os datasets filhos e seus snapshots.
Atualização incremental recursiva:
sudo zfs snapshot -r reservatorio/bancos@2026-03-03
sudo zfs send -R -i reservatorio/bancos@2026-03-02 reservatorio/bancos@2026-03-03 | \
ssh servidor-backup.example.com "sudo zfs receive -F backup_pool/bancos"
Automatizando a Replicação com Scripts
Aqui está um script prático para replicação diária incremental:
#!/bin/bash
# Script para replicação incremental automática com ZFS
set -euo pipefail
POOL_ORIGEM="reservatorio"
DATASET_ORIGEM="bancos"
SERVIDOR_DESTINO="servidor-backup.example.com"
POOL_DESTINO="backup_pool"
DATASET_DESTINO="$DATASET_ORIGEM"
DATA=$(date +%Y%m%d_%H%M%S)
NOVO_SNAPSHOT="${POOL_ORIGEM}/${DATASET_ORIGEM}@diario_${DATA}"
MANTER_SNAPSHOTS=7 # Manter 7 snapshots diários
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
# Encontre o snapshot mais recente na origem e no destino
ULTIMO_ORIGEM=$(zfs list -t snapshot -H -o name -s creation \
| grep "^${POOL_ORIGEM}/${DATASET_ORIGEM}@" \
| tail -1)
ULTIMO_DESTINO=$(ssh "$SERVIDOR_DESTINO" \
"sudo zfs list -t snapshot -H -o name -s creation 2>/dev/null \
| grep '^${POOL_DESTINO}/${DATASET_DESTINO}@' | tail -1" 2>/dev/null || echo "")
# Crie um novo snapshot
log "Criando snapshot: $NOVO_SNAPSHOT"
sudo zfs snapshot -r "$NOVO_SNAPSHOT"
if [ -z "$ULTIMO_DESTINO" ]; then
# Nenhum snapshot no destino - envio completo
log "Nenhum snapshot existente no destino. Realizando envio completo..."
sudo zfs send -R "$NOVO_SNAPSHOT" | \
mbuffer -s 128k -m 1G 2>/dev/null | \
ssh "$SERVIDOR_DESTINO" "sudo zfs receive -F ${POOL_DESTINO}/${DATASET_DESTINO}"
else
# Envio incremental a partir do último snapshot comum
ULTIMO_SNAPSHOT_DESTINO="${POOL_ORIGEM}/${DATASET_ORIGEM}@$(echo $ULTIMO_DESTINO | cut -d@ -f2)"
log "Realizando envio incremental de $ULTIMO_SNAPSHOT_DESTINO para $NOVO_SNAPSHOT"
sudo zfs send -R -i "$ULTIMO_SNAPSHOT_DESTINO" "$NOVO_SNAPSHOT" | \
mbuffer -s 128k -m 1G 2>/dev/null | \
ssh "$SERVIDOR_DESTINO" "sudo zfs receive -F ${POOL_DESTINO}/${DATASET_DESTINO}"
fi
# Remova snapshots antigos na origem
log "Removendo snapshots antigos (mantendo $MANTER_SNAPSHOTS)..."
SNAPSHOTS_ANTIGOS=$(zfs list -t snapshot -H -o name -s creation \
| grep "^${POOL_ORIGEM}/${DATASET_ORIGEM}@diario_" \
| head -n -"$MANTER_SNAPSHOTS")
for snapshot in $SNAPSHOTS_ANTIGOS; do
log "Excluindo snapshot antigo: $snapshot"
sudo zfs destroy "$snapshot"
done
log "Replicação concluída."
Agende a execução diária:
echo "30 1 * * * root /usr/local/bin/zfs-replicar.sh >> /var/log/zfs-replicar.log 2>&1" \
| sudo tee /etc/cron.d/zfs-replicacao
Usando o syncoid para Automatizar a Replicação
O syncoid (parte do pacote sanoid) simplifica a replicação incremental:
sudo apt install sanoid
# Configuração inicial: replique reservatorio/web para o servidor de backup
sudo syncoid reservatorio/web servidor-backup.example.com:backup_pool/web
# Atualizações incrementais
sudo syncoid --no-sync-snap reservatorio/web servidor-backup.example.com:backup_pool/web
Agende no cron:
echo "0 2 * * * root syncoid -r reservatorio servidor-backup.example.com:backup_pool >> /var/log/syncoid.log 2>&1" \
| sudo tee /etc/cron.d/syncoid
Opções de Recebimento
- Teste sem aplicar mudanças (dry run):
sudo zfs send reservatorio/web@2026-03-02 | sudo zfs receive -n backup_pool/web - Receber em um dataset diferente:
sudo zfs send reservatorio/web@2026-03-02 | sudo zfs receive backup_pool/web_copia - Substituir propriedades no recebimento:
sudo zfs send reservatorio/web@2026-03-02 | \ sudo zfs receive -o mountpoint=/backup/web backup_pool/web - Receber sem montar:
sudo zfs receive -u backup_pool/web
Restaurando de um Backup Remoto
Para restaurar dados do servidor de backup:
# Envie do backup de volta para a origem (ou um novo servidor)
ssh servidor-backup.example.com \
"sudo zfs send backup_pool/web@diario_20260302_020000" | \
sudo zfs receive -F reservatorio/web_restaurado
Para recuperação completa de um pool:
# Em um novo servidor com um pool ZFS recém-criado
ssh servidor-backup.example.com \
"sudo zfs send -R backup_pool@ultimo_snapshot" | \
sudo zfs receive -F novo_pool
Considerações de Desempenho e Largura de Banda
- Compressão do fluxo:
sudo zfs send reservatorio/web@2026-03-02 | \ gzip | \ ssh servidor-backup.example.com "gunzip | sudo zfs receive backup_pool/web"Observação: Se o dataset já estiver comprimido, ogzippode não adicionar benefícios significativos. - Limitar largura de banda:
sudo zfs send reservatorio/web@2026-03-02 | \ pv -L 10m | \ ssh servidor-backup.example.com "sudo zfs receive backup_pool/web"
Conclusão
O zfs send e zfs receive são ferramentas essenciais para uma estratégia de backup robusta com ZFS. Combinados com snapshots automatizados e replicação remota, eles oferecem recuperação pontual e atualizações incrementais eficientes.
Dica para o seu blog: Adicione exemplos práticos de uso em cenários reais, como migração de servidores ou recuperação de desastres, para enriquecer ainda mais o conteúdo!
Se precisar de mais ajustes ou quiser incluir outros tópicos, é só me avisar!