我已经复制了数 TB 的文件,rsync
但我忘了使用它--archive
来保留文件的特殊属性。
rsync
这次我尝试再次执行--archive
,但速度比我预期的要慢得多。有没有简单的方法可以通过递归复制元数据来更快地完成此操作?
答案1
--reference
好的,您可以使用参数 to 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
通常使用相等的修改时间作为启发式方法来检测和跳过未更改的文件。如果没有--archive
(具体来说,没有--times
),目标文件的修改时间将保持设置为您对其进行 rsync 的时间,而源文件的修改时间保持不变(忽略您的手动欺骗)。如果没有您从外部保证源文件的内容没有更改,rsync 必须假设它们可能已更改,因此必须对它们进行校验和和/或再次将它们复制到目标。再加上--whole-file
local->local 同步所隐含的事实,使得rsync
without--times
大致相当于cp
local 同步。
假设更新目标文件的内容是可以接受的,或者源文件自原始复制以来没有被触及,那么你应该会发现它rsync --archive --size-only
比简单的 rsync 更快。
如果您对rsync
复制的内容有疑问,为什么花了这么长时间,它rsync --archive --dry-run --itemize-changes ...
会以简洁、详尽的方式告诉您。
答案3
警告:如果没有特殊的解决方法,GNUcp --attributes-only
将截断目标文件,至少在 Precise 中如此。请参阅下面的编辑。
原来的:
在这种情况下,您可能需要 GNU cp 的--attributes-only
选项,以及--archive
,因为它是经过试验和测试的代码,具有所有与文件系统无关的属性并且不遵循符号链接(遵循它们可能会很糟糕!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
与文件一样,cp
具有扩展属性:如果源和目标都具有扩展属性,则添加将源的扩展属性复制到目标(而不是先删除目标的所有扩展属性)。虽然这反映了cp
将文件复制到现有树中时的行为,但可能不是您所期望的。
还要注意,如果你第一次没有保留硬链接,rsync
但现在想保留它们,那么cp
惯于为你解决这个问题;你最好rsync
用正确的选项重新运行(见我的其他答案)并且保持耐心。
如果你在寻找故意地分离并重新组合元数据/文件内容,那么你可能需要看看元存储它位于 Ubuntu 存储库中。
编辑后添加:
cp
GNU coreutils
>= 8.17 及以上版本将按所述方式工作,但 coreutils <= 8.16 将在恢复元数据时截断文件。如有疑问,请勿cp
在这种情况下使用;rsync
使用正确的选择和/或保持耐心。
除非你完全理解自己在做什么,否则我不会推荐这样做,但是早期的 GNUcp
可以使用以下方法阻止截断文件: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