Truques para compactar e transferir diretórios com tar e ssh pipes

1. Fundamentos do pipe tar + ssh

O comando combinado tar com ssh via pipe é uma das técnicas mais poderosas para transferir diretórios entre máquinas remotas. A sintaxe básica é:

tar czf - /pasta | ssh user@host "tar xzf - -C /destino"

Neste comando, tar compacta o diretório /pasta com gzip e envia o fluxo binário para a saída padrão (-). O pipe (|) redireciona esse fluxo para o ssh, que executa remotamente outro tar para descompactar e extrair no diretório /destino.

As vantagens sobre scp e rsync tradicionais são significativas:
- Streaming contínuo: não há necessidade de criar arquivos temporários no disco local ou remoto
- Redução de latência: o processo de compactação e transferência ocorre simultaneamente
- Eficiência de espaço: evita o consumo de disco com arquivos intermediários

2. Compactação inteligente durante a transferência

A escolha do algoritmo de compressão impacta diretamente no desempenho:

# Com gzip (padrão, rápido)
tar czf - /dados | ssh user@host "tar xzf - -C /backup"

# Com bzip2 (melhor compressão, mais lento)
tar cjf - /dados | ssh user@host "tar xjf - -C /backup"

# Com xz (alta compressão, muito lento)
tar cJf - /dados | ssh user@host "tar xJf - -C /backup"

# Com zstd (moderno, rápido e boa compressão)
tar --zstd -cf - /dados | ssh user@host "tar --zstd -xf - -C /backup"

Para monitorar o throughput em tempo real, utilize o pv (pipe viewer):

tar czf - /dados | pv -s $(du -sb /dados | awk '{print $1}') | ssh user@host "tar xzf - -C /backup"

3. Preservação de metadados e permissões

A preservação de metadados é crucial para backups consistentes:

# Preservar permissões, proprietários e timestamps
tar czpf - /dados | ssh user@host "tar xzpf - -C /backup"

# Preservar links simbólicos como links
tar czphf - /dados | ssh user@host "tar xzphf - -C /backup"

# Preservar ACLs e atributos estendidos
tar czpf --acls --xattrs - /dados | ssh user@host "tar xzpf --acls --xattrs - -C /backup"

O parâmetro -p (ou --preserve-permissions) mantém proprietários, grupos e permissões originais. Para ambientes com requisitos rigorosos de conformidade, inclua --acls e --xattrs.

4. Exclusão e inclusão seletiva de arquivos

Evite transferir arquivos desnecessários com exclusões inteligentes:

# Excluir diretórios temporários comuns
tar czf - --exclude='node_modules' --exclude='.git' --exclude='cache' /projeto | ssh user@host "tar xzf - -C /destino"

# Usar arquivo de regras de exclusão
echo "*.log" > /tmp/excludes.txt
echo "temp/*" >> /tmp/excludes.txt
tar czf - --exclude-from=/tmp/excludes.txt /dados | ssh user@host "tar xzf - -C /destino"

Para inclusão seletiva de arquivos específicos:

# Usar arquivo de lista de inclusão
find /dados -name "*.conf" -type f > /tmp/include.txt
tar czf - -T /tmp/include.txt | ssh user@host "tar xzf - -C /destino"

5. Transferência incremental e retomada de falhas

Para backups incrementais, combine tar com rsync:

# Sincronização diferencial com rsync
rsync -avz --progress /dados/ user@host:/backup/

# Backup incremental com tar --listed-incremental
tar czpf - --listed-incremental=/tmp/snapshot.snar /dados | ssh user@host "tar xzpf - -C /backup"

Para retomar transferências interrompidas, divida o arquivo em partes:

# Local: dividir em partes de 1GB
tar czf - /dados | split -b 1G - /tmp/backup.tar.gz.part

# Enviar partes individualmente
for part in /tmp/backup.tar.gz.part*; do
  cat "$part" | ssh user@host "cat >> /backup/backup.tar.gz"
done

6. Otimização de desempenho e segurança

Acelere a compressão com algoritmos paralelos:

# Usar pigz (gzip paralelo) no pipe
tar cf - /dados | pigz -p 4 | ssh user@host "unpigz | tar xf - -C /destino"

# Compressão remota vs. local (testar qual é mais rápido)
# Opção 1: compressão local
tar cf - /dados | gzip -1 | ssh user@host "gunzip | tar xf - -C /destino"

# Opção 2: compressão remota
tar cf - /dados | ssh user@host "gzip | tar xzf - -C /destino"

Adicione criptografia para dados sensíveis:

# Criptografar com openssl
tar czf - /dados | openssl enc -aes-256-cbc -salt -pass pass:senha123 | ssh user@host "openssl enc -d -aes-256-cbc -pass pass:senha123 | tar xzf - -C /destino"

# Criptografar com gpg
tar czf - /dados | gpg -e -r usuario@email.com | ssh user@host "gpg -d | tar xzf - -C /destino"

7. Casos de uso avançados e automação

Script para backup remoto diário com rotação:

#!/bin/bash
# backup_remoto.sh
DATA=$(date +%Y%m%d)
ORIGEM="/dados"
DESTINO="user@host:/backup/$DATA"
LOG="/var/log/backup.log"

echo "[$(date)] Iniciando backup de $ORIGEM" >> $LOG
tar czpf - --exclude='.cache' $ORIGEM | ssh user@host "mkdir -p /backup/$DATA && tar xzpf - -C /backup/$DATA" 2>> $LOG

if [ $? -eq 0 ]; then
    echo "[$(date)] Backup concluído com sucesso" >> $LOG
else
    echo "[$(date)] ERRO no backup" >> $LOG
fi

Para transferências de diretórios muito grandes, use mbuffer para evitar gargalos:

tar cf - /dados_gigantes | mbuffer -s 128k -m 512M | ssh user@host "mbuffer -s 128k -m 512M | tar xf - -C /destino"

Integração com cron para transferências agendadas:

# /etc/cron.d/backup_remoto
0 2 * * * root /usr/local/bin/backup_remoto.sh >> /var/log/backup_cron.log 2>&1

Referências