Skip to topic | Skip to bottom
www.postcogito.org
          ...sine propero notiones
Kiko
Você está aqui: Kiko > SoftwareEUtilitarios > ProgramaDeltaCP Imprimível | fim do tópico


Start of topic | Skip to actions
English Version

O programa deltacp.pl

O programa deltacp.pl copia um arquivo (normalmente um dispositivo de bloco) para outra máquina de forma a enviar apenas as diferenças entre eles.

Lista de Discussão

Veja a lista de discussão do deltacp. Clique aqui para assiná-la.

Licença e Downloads

Este programa é disponibilizado nos termos da CC-GNU GPL 2.0.

Sinopse

  • Modo originador (ou "gerador de diferenças"):
    deltacp.pl opções origem destino

  • Modo de recebimento (ou "aplicação das diferenças"):
    deltacp.pl opções -O arquivo

origem é um arquivo local, normalmente um dispositivo de bloco tal como /dev/hdb ou /dev/vg0/lv0.

destino é da forma usuário@máquina:arquivo e aponta para o arquivo de destino na máquina remota.

As opções podem ser zero ou mais dentre as seguintes:

-v Modo falante, repita para mais tagarelice
-b value Define o tamanho do bloco (65536 por padrão)
-L filename Define o nome do arquivo de log de recebimento. Não é gerado se não for especificado.
-O filename Coloca o programa em modo de recebimento e especifica o nome do arquivo onde as mudanças serão aplicadas.
O arquivo com as diferenças deve vir na entrada padrão.
-d filename Salva os blocos originais no arquivo especificado (i.e., cria arquivo de diferenças reversas)
-D filename Salva os blocos modificados no arquivo especificado (i.e., cria arquivo de diferenças diretas)
-x args Passa os args para o ssh (tal como -C para ativar a compressão ou -o 'algo')
-F Modo forçado: desativa as checagens de anti-desastre (tal como escrever em um dispositivo que está montado)
-q Modo silencioso: sumprime todas as mensagens exceto as de erro
-n Modo ensaio: faz quase tudo exceto efetivamente alterar o arquivo de destino (mas gera os diffs)
-c Cria o arquivo de saída caso ele não exista
-e Apaga os arquivos de diferenças caso eles acabem ficando com 0 bytes
-t Truca o arquivo de saída para torná-lo do mesmo tamanho do origial
-a Anexa a um arquivo de diferenças já existente
-s bloco Especifica o bloco inicial
-r tentativas Determina quantas vezes tentar de novo em caso de falha
-P tempo Pausa (em segundos) entre as tentativas. Dobrada (até um máximo de 300 segundos) a cada nova tentativa

Descrição

Modo normal

Entra-se neste modo quando tanto o arquivo de origem quanto o destino são especificados na linha de comando. O programa dispara uma sessão ssh para a máquina remota, logando com o usuário especificado. Lá ele executará uma outra instância que receberá e aplicará as mudanças geradas pela instância local. Se você omitir tanto máquina quanto usuário, o programa operará localmente sem usar o ssh.

Ao invocar a outra instância, seja localmente ou por ssh, o originador repassa as opções -D, -d, -n, -e, -t, -F and -b para a outra instância. Ademais, ele adiciona as opções -qc e, é claro, -O.

A instância local lê o arquivo de origem bloco por bloco, calcula o hash de cada bloco e os envia para a instância remota. Esta, por sua vez, realiza os mesmos cálculos a partir do arquivo de destino. Se os hashes forem diferentes, ela requisitará os blocos completos. Ao recebê-los, ele os aplicam por sobre o arquivo de destino.

Se a opção -d tiver sido especificada, a instância remota salvará os blocos antes de aplicá-los, criando um outro arquivo binário com as "diferenças reversas" que podem ser usadas para posteriormente reverter a operação.

Se a opção -D tiver sido especificada, a instância remota salvará os blocos após tê-los aplicado, criando um outro arquivo binário com as "diferenças diretas" que podem ser usadas para refazer a operação.

Normalmente o programa não sobrescreve os arquivos de diferenças se eles já existirem, para evitar que os usuários acidentalmente destruam diffs importantes. A opção --force pode ser usada para forçar isso.

Pode-se também anexar a um arquivo de diferenças já existente usando a opção -a. Isso é útil para continuar uma sessão que tenha sido interrompida.

À medida em que o programa roda, ele mostra estatísticas incluindo quantos blocos foram transferidos até o momento. Se o tamanho do arquivo é conhecido de antemão, será impresso também o número total de blocos e a posição atual como percentagem do total. Se mais de cinco segundos tiverem se passado desde o início da transferência, uma estimativa do tempo restante é mostrada.

Outras estatísticas incluem também quantos blocos foram realmente transferidos por terem havido diferenças e quantos foram pulados por terem sido iguais.

Se o destino é um arquivo comum e for maior que o original, seu tamanho só será truncado para ficar do tamanho do original se a opção -t tiver sido explicitamente incluída. Caso contrário, seu tamanho não será alterado.

Se o tamanho do arquivo de origem for maior do que o de destino, duas coisas podem acontecer: se o destino for um dispositivo de bloco, um erro ocorrerá, pois eles não podem aumentar de tamanho (volumes lógicos até podem, mas não automaticamente). Já se o destino for um arquivo comum, ele crescerá para ficar do tamanho do original, desde que o espaço em disco restante assim o permita.

O programa tentará evitar que o usuário faça algo potencialmente destrutivo tal como sobrescrever um sistema de arquivos que está montado ou várias instâncias do programa operando simultaneamente nos mesmos arquivos/dispositivos.

Caso a conexão quebre durante a transferência, o programa se chamará de novo para continuar o envio de onde parou. A cada nova tentativa ele faz uma pausa. Isso é útil quando se está usando o programa sob um link banda larga ou dialup que fica caindo o tempo todo, como em certos hotéis.

Modo de recebimento

Normalmente quem invoca esse modo é a instância originadora, mas pode também ser usado "na mão" para processar os arquivos de diferenças diretas e reversas.

O que define o modo de recebimento é a presença da opção -O, que especifica em qual arquivo as alterações serão aplicadas. Nesse caso, a seqüência de comandos de alteração deverá vir da entrada padrão. (É isso que torna o programa ameno a ser rodado via ssh pela instância remota).

As opções -d e -D podem ser usadas para salvar os blocos antes e depois da aplicação das alterações, respectvicamente, de forma a gerar os arquivos de diferenças. Se a opção -e também tiver sido especificada, quaisquer arquivos de diferenças que acabem ficando vazios são deletados.

Se a opção -n estiver presente, o arquivo especificado em -O não será modificado. Isso é útil quando você só quer gerar as diferenças sem de fato alterar o arquivo da imagem.

A opção -t força o arquivo especificado em -O a ficar do mesmo tamanho do arquivo original. Isso funcionará menso que a opção -n também esteja presente. O tamanho do arquivo original não apenas é passado no protocolo, mas também fica armazenado nos arquivos de diferenças.

A opção -t cria o arquivo especificado em -O caso ele não já exista. Sem ela, obtém-se um erro ao especificar um arquivo inexistente.

Exemplos

Nos exemplos abaixo, o que você deve digitar está em negrito. O resto são as respostas dos programas.

Esses exemplos requerem que seu kernel suporte o dispositivo de loopback de forma a podermos fingir que um arquivo comum é um dispositivo de bloco. Se seu kernel não suportar esse recurso, você pode substituir os arquivos *.img por algo que aponte para partições reais extras cujos dados você não se importe em destruir. Contudo, é capaz dos exemplos levarem bem mais tempo porque o tamanho das suas partições provavelmente é bem maior que os meros 16MB que usamos abaixo.

Backup Simples de um Volume

Criemos um arquivo de 16MB totalmente preenchido com bytes zero para servir de espaço para brincarmos ('local$ ' é o prompt normal, sem ser de root, na primeira máquina):

local$ dd if=/dev/zero of=example.img bs=16k count=1000
1000+0 records in
1000+0 records out

Façamos o mesmo na máquina remota. Esse espaço será nosso "volume de backup remoto":

remote$ dd if=/dev/zero of=backup.img bs=16k count=1000
1000+0 records in
1000+0 records out
16384000 bytes (16 MB) copied, 0,584972 seconds, 28,0 MB/s

Criemos um sistema de arquivos ext2 no espaço criado (o resultado do seu mkfs.ext2 poderá ser um pouco diferente):

local$ yes | /sbin/mkfs.ext2 example.img
mke2fs 1.35 (28-Feb-2004)
example.img is not a block special device.
Proceed anyway? (y,n) Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
4000 inodes, 16000 blocks
800 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=16515072
2 block groups
8192 blocks per group, 8192 fragments per group
2000 inodes per group
Superblock backups stored on blocks:
        8193

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 31 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Agora, vamos montá-lo usando o dispositivo de loopback. Note o prompt com "#" indicando que você precisa dos poderes de root para isso:

local$ /bin/su
Password: (sua senha de root)
local# mkdir /mnt/example
local# mount -t ext2 -o loop example.img /mnt/example

Coloquemos alguma coisa nele:

local# cp /bin/b* /mnt/example
local# ls -l /mnt/example
total 733
-rwxr-xr-x  1 root root  15444 Feb 23 12:02 basename
-rwxr-xr-x  1 root root 616248 Feb 23 12:02 bash
-rwxr-xr-x  1 root root  98356 Feb 23 12:02 bsh
drwx------  2 root root  12288 Feb 23 12:01 lost+found

No meu exemplo eu tinha apenas três arquivos porque eu estava usando uma máquina com uma instalação minimalista recém terminada. No seu caso provavelmente haverá mais.

Vamos desmontar a imagem de forma que ela fique estática e consistente:

local# umount /mnt/example
local# exit

Agora vamos usar o deltacp.pl para copiá-la por sobre o arquivo de backup na outra máquina.

local$ deltacp.pl example.img user@remote:backup.img
  current/total   current% | skips%      sent/skips
      250/250       100.0% |  92.8%        18/232       ---d --:--:--

Note que apenas 18 blocos foram realmente transferido dentre o total de 250; evitamos transmitir 92.8% deles (ou seja, 232 blocks). Seus valores exatos muito provavelmente serão diferents, é claro.

Vamos nos convencer de que os dois arquivos são idênticos. Na máquina local, faça:

local$ md5sum example.img
6d7adfd8306c35ff6322a8060e0417f7  example.img

E na remota:

remote$ md5sum backup.img
6d7adfd8306c35ff6322a8060e0417f7  backup.img

Os hashes batem, entao os arquivos são idênticos. O valor exato dos seus hashes será diferente, é claro).

Recuperando Arquivos Sobrescritos

Vamos simular um desastre comum: sobrescrever um arquivo importante. Usaremos então o recurso de 'dif reverso' para restaurar o sistema de arquivos a um estado anterior de sorte a podermos acessar o conteúdo do arquivo original antes de ter sido sobrescrito. Por generalidade, esse exemplo usará o bash e o tar, mas imagine que o bash fosse algo muito importante para você, tal como o seu relatório final cujo prazo final é amanhã e cujas muitas notas muitas noites em claro que você investiu nele correm o risco de ir por água abaixo por causa de um instante de distração.

Reusaremos o sistema de arquivos que criamos no exemplo anterior. Primeiro, vamos remontá-lo. Em seguida, vamos simular o desastre, sobrescrevendo o super-importante executável /bin/bash. Por fim, desmontaremos o sistema de arquivos.

local% /bin/su
Password: (your root password)
local# mount -t ext2 -o loop example.img /mnt/example
local# cp /bin/tar /mnt/example/bash
cp: overwrite `/mnt/example/bash'? y
local# umount /mnt/example
local# exit

Vamos agora usar o deltacp.pl para sincronizá-los. Dessa vez, entretanto, vamos criar um arquivo de diferenças reversas com marcação de data/hora:

local% <b>deltacp.pl -d backup.img-diff-`date +%y%m%d-%H%M%S` example.img user@remote:backup.img</b>
  current/total   current% | skips%     skips/sent
      250/250       100.0% |  98.0%         5/245       ---d --:--:--

Agora vamos ver o que obtivemos na máquina remota:

Now, let's see what we have in the remote:

kiko@melee:~$ ls -l backup.img*
-rw-r--r-- 1 kiko kiko 16384000 2007-02-23 12:38 backup.img
-rw-r--r-- 1 kiko kiko   327805 2007-02-23 12:38 backup.img-diff-070223-113928

Tanto atualizamos a imagem quanto também geramos a dif reversa.

Vamos agora montar a imagem de backup no remoto em modo somente leitura e examinar o programa bash:

remote% /bin/su
Password: (your root password)
remote# mkdir /mnt/backup
remote# mount -t ext2 -o ro,loop backup.img /mnt/backup
remote# ls -l /mnt/backup
total 286
-rwxr-xr-x 1 root root  15444 2007-02-23 11:27 basename
-rwxr-xr-x 1 root root 161188 2007-02-23 11:36 bash
-rwxr-xr-x 1 root root  98356 2007-02-23 11:27 bsh
drwx------ 2 root root  12288 2007-02-23 11:27 lost+found
remote# /mnt/backup/bash --version
tar (GNU tar) 1.14
Copyright (C) 2004 Free Software Foundation, Inc.
This program comes with NO WARRANTY, to the extent permitted by law.
You may redistribute it under the terms of the GNU General Public License;
see the file named COPYING for details.
Written by John Gilmore and Jay Fenlason.

Opa! O bash não é o bash, é o tar! Como se a gente não soubesse disso. Mas em uma situação real de desastre, provavelmente ficaríamos surpresos, ou até chocados, em descobrir que nosso precioso arquivo fora sobrescrito -- ou seja, zero chance de ferramentas de "desapagamento" terem sucesso.

Vamos à recuperação: vamos desmontar o sistema de arquivos, aplicar o arquivo de diferenças reversas para fazê-lo "voltar no tempo", remontá-lo e ver no que dá:

remote# umount /mnt/backup
remote# exit
remote$ deltacp.pl -O backup.img < backup.img-rdiff-070223-113928
remote$ /bin/su
Password: (your root password)
remote# mount -t ext2 -o loop backup.img /mnt/backup
remote# /mnt/backup/bash --version
GNU bash, version 3.00.15(1)-release (i386-redhat-linux-gnu)
Copyright (C) 2004 Free Software Foundation, Inc.
remote# umount /mnt/backup

Agora o bash é novamente o bash.

Coalescência

Suponha que tenhamos vários arquivos de diferenças reversas geradas por nossa rotina de backup diário e queremos voltar a imagem alguns dias no tempo para recuperar algum material deletado. Vamos primeiro dar uma olhada nelas e dar uma olhada no estado da nossa imagem.

local$ ls -l rdiff-07022*
-rw-r--r--   1 kiko kiko    6490539 2007-02-20 01:29 rdiff-070220
-rw-r--r--   1 kiko kiko   46220530 2007-02-21 23:37 rdiff-070221
-rw-r--r--   1 kiko kiko  102275185 2007-02-22 22:20 rdiff-070222
local$ md5sum /dev/sda3
99118e13e6e535bd4c3f5e0df8fbe2ba  /dev/sda3

Agora vamos aplicá-las (em ordem reversa, é claro), ao mesmo tempo em que geramos um arquivo de diferenças reversas coalescidas para que possamos posteriormente voltar ao estado presente.

local$ cat `ls rdiff-07222* | sort -r` | deltacp.pl -d rdiff-coalesced -O /dev/sda2

O arquivo de diferenças coalescidas, contudo, é menor do que a soma das diferenças individuais porque o programa não salva o bloco trocado mais de uma vez:

local$ ls -l rdiff-coalesced
-rw-r--r--   1 kiko kiko  118009825 2007-02-23 09:11 rdiff-coalesced

Em todo caso, nesse ponto poderíamos montar o sistema de arquivos em /dev/sda3, recuperar nosso material, e por aí vai. Ao terminarmos, desmontaríamos o volume e o restauraríamos ao estado anterior usando as diferenças coalescidas:

local$ deltacp.pl -O /dev/sda3 < rdiff-coalesced
-rw-r--r--   1 kiko kiko  118009825 2007-02-23 09:11 rdiff-coalesced
local$ md5sum /dev/sda3
99118e13e6e535bd4c3f5e0df8fbe2ba  /dev/sda3
local$ rm rdiff-coalesced

Motivação

O rsync é um programa de backup/espelhamento diferencial cheio de recursos que faz muito e muito mais do que o deltacp.pl faz -- mas ele não lê nem escreve em dispositivos de bloco: ele reclama com a mensagem 'skipping non-regular file' se você tentar.

Folheando pelos arquivos da lista de discussão do rsync, descobri que essa questão vez por outra é levantada. Foi proposto até um patch para isso, mas é para uma versão 2.5.5 antigona, sem muito das features e atualizações de seguranças recentes. O consenso na lista parece ser que esse recurso é mais indicado para um utilitário próprio para isso e por isso o rsync não o suportará.

O Protocolo

O arquivo é dividido em blocos de igual tamanho, exceto possivelmente o último, se o tamanho do arquivo não for um múltiplo do tamanho do bloco.

Para cada bloco, o originador transmite uma mensagem de 25 bytes:

  • Comando: 1 byte
  • Número do bloco: 4 bytes, como um inteiro longo big-endian
  • Comprimento do bloco: 4 bytes, como um inteiro longo big-endian
  • Hash do bloco: 16 bytes, usando o algoritmo MD5.

O destinatário computa o hash do bloco especificado e o compara com o recebido. Se baterem, ele responde 0x0, significando "não me mande o bloco, pois ele é igual ao que eu tenho". Caso contrário, ele responde com 0x1, significando "por favor me envie esse bloco, pois ele difere do que eu tenho"

Se o originador receber um 0x1, ele manda o bloco completo. Caso contrário, ele passa direto para o próximo bloco. O processo é repetido até se chegar ao fim do arquivo.

Sobrecarga

Se os arquivos de origem e destino forem totalmente diferentes, o programa adiciona exatamente

25*int((file_size+block_size-1)/block_size)

bytes extras. Isso dá cerca de 15MB para cada 40GB de dados -- meros 0,038%, se usarmos o tamanho padrão dos blocos.

Isso significa que esses 15MB serão transferidos mesmo que nada tenha mudado.

Características Dinâmicas

Sendo um protocolo tipo "pare-e-aguarde", sua eficiência é dominada pela latência: funciona melhor em redes locais onde a latêntica tipicamente é menor que um milissegundo.

Por outro lado, o tamanho default dos blocos, sendo bem maior do que os pacotes TCP, dissipa um pouco esse efeito em links com latências de várias dezenas de milissegundos, como é o caso da Internet ou VPNs.

Prerequisitos e Instalação

O programa requer Perl 5, preferivelmente com suporte a arquivos grandes (>2GB).

Para checar se seu Perl satisfaz esse requisito, digite:

perl -V | grep -ic USE_LARGE_FILES.

Se você obtiver 1, seu Perl quase certamente é adequado. Se você obtiver 0, o deltacp.pl ainda funcionará, mas só conseguirá tratar arquivos de até 2GB.

Por padrão o programa usa seu cliente SSH: se você conseguir conectar na máquina remota via ssh, o deltacp.pl também o conseguirá.

Para instalar, descompacte-o no /usr/local/bin e defina as permissões para 755. Certifique-se de que este diretório está listado em algum lugar da variável de ambiente PATH.
topo


Você está aqui: Kiko > SoftwareEUtilitarios > ProgramaDeltaCP

topo

Creative Commons License   O conteúdo deste site está disponibilizado nos termos de uma Licença Creative Commons, exceto onde dito em contrário.
  The content of this site is made available under the terms of a Creative Commons License, except where otherwise noted.