Я уже скопировал терабайты файлов с помощью, rsync
но забыл использовать --archive
функцию сохранения специальных атрибутов файлов.
Я попробовал выполнить rsync
снова на этот раз с помощью , --archive
но это было намного медленнее, чем я ожидал. Есть ли какой-нибудь простой способ сделать это быстрее, просто рекурсивно скопировав метаданные?
решение1
Хорошо, вы можете скопировать владельца, группу, разрешение и временные метки, используя --reference
параметр в chown
, chmod
, touch
. Вот скрипт для этого
#!/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
Вам следует запустить его с sudo
(чтобы разрешить chown) и с двумя параметрами: исходный и целевой каталоги. Скрипт только выводит то, что он будет делать. Если все в порядке, измените строку myecho=echo
с помощью myecho=
.
решение2
Если рассматривать вопрос так: «rsync копирует только метаданные, так почему же он такой медленный и как его ускорить?»:
rsync
обычно использует равные mtimes в качестве эвристики для обнаружения и пропуска неизмененных файлов. Без --archive
(в частности, без --times
) mtimes файлов назначения остаются установленными на время, когда вы их rsync-или синхронизировали, в то время как mtimes исходных файлов остаются нетронутыми (игнорируя ваши ручные уловки). Без внешних гарантий с вашей стороны, что содержимое исходных файлов не изменилось, rsync должен предположить, что они могли измениться, и поэтому должен проверить их контрольную сумму и/или снова скопировать их в место назначения. Это, а также тот факт, что --whole-file
подразумевается для локальных->локальных синхронизаций, делает rsync
без --times
приблизительно эквивалентным cp
для локальных синхронизаций.
При условии, что обновление содержимого целевых файлов приемлемо или если исходные файлы не были затронуты с момента создания оригинальной копии, вы должны найти rsync --archive --size-only
более быстрый способ, чем простой rsync.
Если у вас есть сомнения относительно того, что rsync
копирование занимает так много времени, rsync --archive --dry-run --itemize-changes ...
расскажет вам исчерпывающую, хотя и лаконичную, информацию.
решение3
ВНИМАНИЕ: Без специальных обходных путей GNU cp --attributes-only
обрежет файлы назначения, по крайней мере в Precise. См. правку ниже.
Оригинал:
В этой ситуации вам, вероятно, понадобится опция GNU cp --attributes-only
вместе с --archive
, поскольку это проверенный и испытанный код, который выполняет все атрибуты, не зависящие от файловой системы, и не следует по символическим ссылкам (следование по ним может быть плохим!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
Как и в случае с файлами, cp
является аддитивным с расширенными атрибутами: если и источник, и назначение имеют расширенные атрибуты, тодобавляетрасширенные атрибуты источника в место назначения (вместо того, чтобы сначала удалить все xattrs места назначения). Хотя это отражает то, как cp
ведет себя копирование файлов в существующее дерево, это может быть не то, что вы ожидаете.
Также обратите внимание, что если вы не сохранили жесткие ссылки в первый раз, rsync
но хотите сохранить их сейчас, тоcp
не будетисправить это для вас; вам, вероятно, лучше всего будет перезапустить rsync
с правильными параметрами (см. мойдругой ответ) и будьте терпеливы.
Если вы нашли этот вопрос, когда искалиумышленноразделите и заново объедините метаданные/содержимое файла, тогда вам, возможно, захочется взглянуть наметасторкоторый находится в репозиториях Ubuntu.
Источник:Руководство по GNU coreutils
Отредактировано для добавления:
cp
из GNU coreutils
>= 8.17 и выше будет работать, как описано, но coreutils <= 8.16 будет обрезать файлы при восстановлении их метаданных. Если сомневаетесь, не используйте cp
в этой ситуации; используйте rsync
справильные вариантыи/или будьте терпеливы.
Я бы не рекомендовал этого делать, если вы не понимаете полностью, что делаете, но в более ранних версиях GNU cp
можно запретить обрезание файлов с помощьюТрюк 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);
}
решение4
При локальных передачах, когда источник и место назначения находятся на локально смонтированных файловых системах, rsync
всегда будет копироваться все содержимое файлов. Чтобы избежать этого, вы можете использовать
rsync -a --no-whole-file source dest