Já copiei terabytes de arquivos, rsync
mas esqueci de usar --archive
para preservar os atributos especiais dos arquivos.
Tentei executar rsync
novamente desta vez, --archive
mas foi bem mais lento do que eu esperava. Existe alguma maneira fácil de fazer isso mais rápido, apenas copiando metadados recursivamente?
Responder1
Ok, você pode copiar proprietário, grupo, permissão e carimbos de data e hora usando o --reference
parâmetro para chown
, chmod
, touch
. Aqui está um script para fazer isso
#!/bin/bash
# Filename: cp-metadata
myecho=echo
src_path="$1"
dst_path="$2"
find "$src_path" |
while read src_file; do
dst_file="$dst_path${src_file#$src_path}"
$myecho chmod --reference="$src_file" "$dst_file"
$myecho chown --reference="$src_file" "$dst_file"
$myecho touch --reference="$src_file" "$dst_file"
done
Você deve executá-lo com sudo
(para permitir chown) e com dois parâmetros: diretório de origem e destino. O script apenas ecoa o que faria. Se estiver satisfeito, altere a linha myecho=echo
com myecho=
.
Responder2
Tratar a questão como "o rsync só possui metadados para copiar, então por que é tão lento e como posso torná-lo mais rápido?":
rsync
geralmente usa mtimes iguais como heurística para detectar e ignorar arquivos inalterados. Sem --archive
(especificamente, sem --times
) os mtimes dos arquivos de destino permanecem definidos para o horário em que você os sincronizou novamente, enquanto os mtimes dos arquivos de origem permanecem intactos (ignorando seus truques manuais). Sem garantias externas suas de que o conteúdo dos arquivos de origem não foi alterado, o rsync deve assumir que eles podem ter mudado e, portanto, deve verificá-los e/ou copiá-los para o destino novamente. Isso, mais o fato de --whole-file
estar implícito nas sincronizações locais-> locais, torna- rsync
o --times
aproximadamente equivalente ao cp
das sincronizações locais.
Desde que a atualização do conteúdo dos arquivos de destino seja aceitável, ou se os arquivos de origem não foram alterados desde a cópia original, você deve achar rsync --archive --size-only
mais rápido do que um rsync ingênuo.
Em caso de dúvida sobre o que rsync
está demorando tanto para copiar, rsync --archive --dry-run --itemize-changes ...
informe-o em detalhes exaustivos, embora concisos.
Responder3
AVISO: Sem soluções especiais, o GNU cp --attributes-only
truncará os arquivos de destino, pelo menos no Precise. Veja a edição abaixo.
Original:
Nesta situação, você provavelmente deseja --attributes-only
a opção do GNU cp, junto com --archive
, como é um código testado e comprovado, executa todos os atributos independentes do sistema de arquivos e não segue links simbólicos (segui-los pode ser ruim!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
Tal como acontece com os arquivos, cp
é aditivo com atributos estendidos: se a origem e o destino tiverem atributos estendidos,adicionaos atributos estendidos da origem para o destino (em vez de excluir primeiro todos os xattrs do destino). Embora isso espelhe o cp
comportamento se você copiar arquivos em uma árvore existente, pode não ser o que você espera.
Observe também que se você não preservou os links físicos da primeira vez, rsync
mas deseja preservá-los agora, entãocp
não vaiconserte isso para você; provavelmente é melhor você executar novamente rsync
com as opções certas (veja meuoutra resposta) e ser paciente.
Se você encontrou esta pergunta enquanto procuravadeliberadamenteseparar e recombinar metadados/conteúdo de arquivo, então você pode querer dar uma olhada emmetastoreque está nos repositórios do Ubuntu.
Fonte:Manual do GNU coreutils
Editado para adicionar:
cp
do GNU coreutils
>= 8.17 e superior funcionarão conforme descrito, mas coreutils <= 8.16 truncará arquivos ao restaurar seus metadados. Em caso de dúvida, não utilize cp
nesta situação; usar rsync
comas opções certase/ou seja paciente.
Eu não recomendaria isso a menos que você entenda completamente o que está fazendo, mas o GNU anterior cp
pode ser impedido de truncar arquivos usando oTruque LD_PRELOAD:
/*
* File: no_trunc.c
* Author: D.J. Capelis with minor changes by Zak Wilcox
*
* Compile:
* gcc -fPIC -c -o no_trunc.o no_trunc.c
* gcc -shared -o no_trunc.so no_trunc.o -ldl
*
* Use:
* LD_PRELOAD="./no_trunc.so" cp --archive --attributes-only <src...> <dest>
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>
extern int errorno;
int (*_open)(const char *pathname, int flags, ...);
int (*_open64)(const char *pathname, int flags, ...);
int open(const char *pathname, int flags, mode_t mode) {
_open = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
flags &= ~(O_TRUNC);
return _open(pathname, flags, mode);
}
int open64(const char *pathname, int flags, mode_t mode) {
_open64 = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
flags &= ~(O_TRUNC);
return _open64(pathname, flags, mode);
}
Responder4
Nas transferências locais, quando a origem e o destino estão em sistemas de arquivos montados localmente, rsync
sempre copiará o conteúdo inteiro dos arquivos. Para evitar isso você pode usar
rsync -a --no-whole-file source dest