Movimento recursivo ('mv -rn', como 'cp -rn'), um movimento que somente moverá arquivos não presentes

4

Contexto

Eu tenho conteúdo enviado pelo usuário que precisa de backup. O conteúdo é superior a 3 servidores separados em /var/www/domain/media/ (em cada servidor está no mesmo local). O backup é um RAID montado em NFS em /var/www/domain/bak/ .

media/ é de propriedade de um usuário diferente de bak/ , basicamente o webapp pode gravar em media/ , mas só pode ler bak/ (os usuários podem excluir seu upload somente até o backup às 00:00 GMT ).

Isso resultou em dois problemas: o usuário pode forçar o mesmo nome de arquivo a sobrescrever o arquivo no backup, e um arquivo em media/ pode acabar em dois servidores diferentes (exatamente o mesmo arquivo se o usuário fizer o upload de dois vezes e é servido por um servidor distinto).

Tudo isso roda em 4 CenOS 7 (web X 3 + backup X 1). Os servidores "web" têm espaço em disco limitado, e é necessário mover as coisas para o servidor de backup para evitar que eles preencham os discos.

Não há nenhuma condição de corrida , então é algo que não precisamos nos importar. O backup é feito a partir da única máquina de backup, executando comandos através de ssh sobre as outras três máquinas, sequencialmente.

Solução atual

A "movimentação" dos arquivos para backup é feita após a eliminação de duplicatas:

find /var/www/domain/media/ -type f | > media
find /var/www/domain/bak/ -type f | awk '{a=gensub("bak","media",1); print a}' > bak
cat bak media | sort | uniq -d > dupes
cat dupes | xargs rm
cp -r /var/www/domain/media/* /var/www/domain/bak/
rm -rf /var/www/domain/media/*

O problema com o uso de mv é que /var/www/domain/media/ tem subdiretórios por usuário. Por exemplo:

media/user13/myvideo.webm
media/user13/walk-in-the-park.webm
media/user16/cat-video.webm
media/user17/presentation-may-2016.webm

bak/user13/mountai-trip.webm
bak/user13/walk-in-the-park.webm
bak/user14/reax-the-dog.webm

O comando deve criar diretórios para user16 e user17 , enquanto deve evitar sobrescrever bak/user13/walk-in-the-park.webm .

Emitir com a solução atual

Gostaria de manter as duplicatas em media/ em vez de excluí-las. Copiá-los para outro lugar cai no mesmo problema, já que novos arquivos virão durante o dia e eu precisarei sincronizar os duplicados com suas cópias.

Como posso mover todos os arquivos media/ que não estão em bak/ mantendo a estrutura de diretório e não removendo os arquivos já presentes.

Em outras palavras, estou procurando um movimento que funcione:

source      | destination         | action
----------- | ------------------- | ----------------------------------
file exists | file does not exist | move ('mv'), source -> destination
file exists | file exists         | do nothing, both files stay as they are
no file     | file exists         | do nothing (will not trigger)
no file     | file does not exist | do nothing (well, there's nothing to do something with!)

Tentativas de uma solução mais elegante

Eu acredito que rsync será capaz de realizar isso. Estou ciente de --remove-source-files , mas não consigo encontrar uma maneira de não verificar os timestamps, as somas de verificação, o tamanho do arquivo, tudo.

Estou mantendo e verificando as somas de verificação como um processo completamente separado.

Eu só me importo com os nomes dos arquivos. Estou ciente de que isso pode levar à corrupção de arquivos, mas receio que seja muito mais fácil obter um arquivo corrompido no disco normal do que no servidor RAID.

Soluções que não são rsync são bem-vindas. Eu pensei em escrever um shell -script para executar o movimento (estenda o script da seção Solução atual ). No entanto, uma vez que eu pensei que seria propenso a erros, eu desisti.

Eu também tentei:

tar -cf /var/www/domain/media | (cd /var/www/domain/bar; tar -kxf -)

Mas é muito lento para arquivos de mídia (o que pode ser bastante grande) e mantém todos os arquivos em media/ (que tem espaço em disco limitado).

    
por grochmal 04.06.2016 / 16:56

1 resposta

3

Para não fazer nada se o arquivo já existir na árvore de destino (independentemente de quaisquer metadados), passe a opção --ignore-existing para rsync.

rsync -a --remove-source-files --ignore-existing /var/www/domain/media/ /var/www/domain/bak/
    
por 06.06.2016 / 00:51