Rsync não faz análise de checksum dos arquivos por padrão
Do man rsync
Rsync finds files that need to be transferred using a “quick check” algorithm (by default) that looks for files
that have changed in size or in last-modified time. Any changes in the other preserved attributes (as requested by
options) are made on the destination file directly when the quick check indicates that the file’s data does not
need to be updated.
Logo, se temos dois arquivos:
mkdir -p /tmp/testersync/{origem,destino}
echo “O rsync nao faz checksum por padrao” > /tmp/testersync/origem/arquivo
Se, um tempo depois, você criar um arquivo igual no destino:
echo “O rsync nao faz checksum por padrao” > /tmp/testersync/destino/arquivo
E usar o rsync:
rsync -avi /tmp/testersync/origem/ /tmp/testersync/destino
sending incremental file list
>f..t…… arquivo
Esse t na saída do log mostra que ele notou que o timestamp está diferente.
Se você mudar o tamanho da frase:
echo “Claro que o rsync faz checksum por padrao, oras” > /tmp/testersync/destino/arquivo
Agora o rsync vai falar que ele mudou não só o timestamp mas o tamanho:
rsync -avi /tmp/testersync/origem/ /tmp/testersync/destino
sending incremental file list
>f.st…… arquivo
Agora vamos tentar enganar o rsync. Vou criar o arquivo com a mesma frase, mas toda em maiúscula:
cat /tmp/testersync/origem/arquivo | tr ‘[a-z]’ ‘[A-Z]’ > /tmp/testersync/destino/arquivo
Do ponto de vista computacional, claramente eles são diferentes:
find /tmp/testersync -type f -exec sha256sum ‘{}’ \+
f27d88d52759a4b07c077f34c230c47b94ea88b6640fc47b44d562243966eb7e /tmp/testersync/destino/arquivo
47c6ec4243572212a13d657637a62975a1007cf5881668cf7d02d370956dc3b3 /tmp/testersync/origem/arquivo
O tamanho é o mesmo:
find /tmp/testersync -type f -printf ‘%P: %s\n’
destino/arquivo: 36
origem/arquivo: 36
Mas se você usar o rsync, ele vai retransferir o arquivo porque o mtime é diferente, e isso é um grande indicador que algo mudou no arquivo:
find /tmp/testersync -type f -printf ‘%P: %t\n’
destino/arquivo: Sun Dec 17 14:45:20.4011998470 2023
origem/arquivo: Sun Dec 17 14:43:11.4812008470 2023
Então, se você executar o rsync, ele vai substituir o arquivo:
rsync -avi /tmp/testersync/origem/ /tmp/testersync/destino
sending incremental file list
>f..t…… arquivo
find /tmp/testersync -type f -exec sha256sum ‘{}’ \+
47c6ec4243572212a13d657637a62975a1007cf5881668cf7d02d370956dc3b3 /tmp/testersync/destino/arquivo
47c6ec4243572212a13d657637a62975a1007cf5881668cf7d02d370956dc3b3 /tmp/testersync/origem/arquivo
Só que isso é bem diferente de executar análise de checksum, que em larga escala, pode ser muito ineficiente.
Vamos enganar o rsync. Primeiro recrio o arquivo diferente:
cat /tmp/testersync/origem/arquivo | tr ‘[a-z]’ ‘[A-Z]’ > /tmp/testersync/destino/arquivo
Depois eu altero os horários dele para ficarem iguais ao da origem (conhece essa função do comando touch?):
touch /tmp/testersync/destino/arquivo -r /tmp/testersync/origem/arquivo
Como o rsync enxerga o arquivo agora?
find /tmp/testersync -type f -printf ‘%P:Tamanho %s, Mtime %t\n’
destino/arquivo:Tamanho 36, Mtime Sun Dec 17 14:43:11.4812008470 2023
origem/arquivo:Tamanho 36, Mtime Sun Dec 17 14:43:11.4812008470 2023
Do ponto de vista do rsync, eles agora são iguais:
rsync -avi /tmp/testersync/origem/ /tmp/testersync/destino
sending incremental file list
sent 85 bytes received 12 bytes 194.00 bytes/sec
total size is 36 speedup is 0.37
Pelo log, você pode ver que ele não transferiu nada, e o checksum segue diferente:
find /tmp/testersync -type f -exec sha256sum ‘{}’ \+
f27d88d52759a4b07c077f34c230c47b94ea88b6640fc47b44d562243966eb7e /tmp/testersync/destino/arquivo
47c6ec4243572212a13d657637a62975a1007cf5881668cf7d02d370956dc3b3 /tmp/testersync/origem/arquivo
Neste tipo de situação – que geralmente é improvável de acontecer, mas não necessariamente impossível, você precisa da flag -c:
rsync -avic /tmp/testersync/origem/ /tmp/testersync/destino
sending incremental file list
>fc…….. arquivo
find /tmp/testersync -type f -exec sha256sum ‘{}’ \+
47c6ec4243572212a13d657637a62975a1007cf5881668cf7d02d370956dc3b3 /tmp/testersync/destino/arquivo
47c6ec4243572212a13d657637a62975a1007cf5881668cf7d02d370956dc3b3 /tmp/testersync/origem/arquivo
Se você quiser garantir que a origem e o destino são iguais, você precisa desta flag. Se você está trabalhando com arquivos que usam algum tipo de empacotamento binário de data (basicamente qualquer coisa), a chance desse tipo de situação passar batido é extremamente baixa. Mas quando você trabalha com muitos arquivos textos com formatos e layouts parecidos e com filesystems extravagantes que podem não expor o mtime adequadamente, você pode cair nessa armadilha.
Autor: Marcelo Rocha