rsync --delete com a pasta de destino do superconjunto

2

Eu tenho um processo rsync que está sincronizando o conteúdo de um repositório de origem (que é controlado por versão) em uma montagem NFS compartilhada.

O cenário (por mais horrível que seja) é que a pasta de destino contém mais conteúdo do que a pasta de origem porque outro conteúdo é sincronizado com a pasta de destino de diferentes origens. Por exemplo, as estruturas de pastas podem ser assim:

source

a/a1.txt
a/a2.txt
b/b1.txt

destino

a/a1.txt
a/a2.txt
a/a3.txt
b/b1.txt
c/c1.txt

(neste exemplo, a/a3.txt e c/c1.txt são sincronizados com o destino de outro lugar. Na prática, isso envolve várias outras origens e o conteúdo / processos para esses não podem ser influenciados.)

Agora diga que a pasta de origem exclui o arquivo a/a2.txt . Usando a configuração existente, esse arquivo não seria excluído no destino; mas usar --delete resultaria na exclusão de outros arquivos e é um requisito para não fazer isso.

Como o --delete pode ser usado neste rsync, mas atende ao requisito? Como o diretório de origem é controlado por versão, é simples o suficiente para obter um antes-e-depois desse diretório, portanto, um backup diferencial poderia ser calculado usando o diretório de origem original como referência, mas esta é a melhor maneira?

    
por cmbuckley 30.05.2018 / 12:38

1 resposta

1

Você não pode usar rsync --delete desta forma. É stateless e não mantém registro de quais arquivos foram deletados entre as execuções. O sinalizador --delete simplesmente instrui rsync a excluir todos os arquivos no destino que não existem na origem.

Para implementar essa exclusão restrita, acho que você precisa manter seu próprio estado. Nem rsync nem unison podem fazer isso por você.

O seguinte não é uma solução completa de erro; é um ponto de partida. (No entanto, ele lida com arquivos com nomes estranhos - incluindo aqueles que contêm uma nova linha incorporada.)

Suponha que dois diretórios src e dst . (Para os propósitos do exemplo, não importa se dst é local ou remoto.)

# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z > .state.src

Sempre que realizamos um backup, execute o seguinte código

# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/

# Determine the set of files to delete in "dst/"
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z | tee .state.src.new |
    LC_ALL=C comm -z - -13 .state.src |
    ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'

# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src

Se a sua versão do comm (como o meu) for mais antiga que o GNU coreutils 8.25 e não tiver o -z flag, você poderá usar esta alternativa alternativa:

# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | tr '
# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/

# Determine the set of files to delete in "dst/"
( cd src && find . -type f  -print0 ) | tr '
# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z > .state.src
\n' '\n
# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/

# Determine the set of files to delete in "dst/"
( cd src && find . -type f -print0 ) | LC_ALL=C sort -z | tee .state.src.new |
    LC_ALL=C comm -z - -13 .state.src |
    ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'

# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src
' | LC_ALL=C sort | tee .state.src.new | LC_ALL=C comm -13 - .state.src | tr '
# Find the current list of files (do this just once, to prep the cache)
( cd src && find . -type f -print0 ) | tr '
# Run the rsync to transfer files. "dst/" could be local
rsync -av src/ remote:dst/

# Determine the set of files to delete in "dst/"
( cd src && find . -type f  -print0 ) | tr '%pre%\n' '\n%pre%' | LC_ALL=C sort | tee .state.src.new |
    LC_ALL=C comm -13 - .state.src |
    tr '%pre%\n' '\n%pre%' |
    ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done'

# That seemed to work, so update the state cache
[[ 0 -eq $? ]] && mv -f .state.src.new .state.src
\n' '\n%pre%' | LC_ALL=C sort > .state.src
\n' '\n%pre%' | ssh remote 'while IFS= read -d "" -r f; do rm -f "dst/$f"; done' # That seemed to work, so update the state cache [[ 0 -eq $? ]] && mv -f .state.src.new .state.src
\n' '\n%pre%' | LC_ALL=C sort > .state.src

Sempre que realizamos um backup, execute o seguinte código

%pre%     
por 30.05.2018 / 12:47

Tags