为什么 rsync 每次调用都会发送相同的文件?

为什么 rsync 每次调用都会发送相同的文件?

我正在使用 rsync 通过 SSH 将文件从 Linux 复制到 Mac。

我的命令如下:

rsync \
    --exclude FOO \
    --exclude BAR \
    -e ssh \
    -rclpvih \
    --delete \
    --stats \
    /local/dir/ \
    host:/remote/dir/

输出如下:

building file list ... done
...
<fc.T...... core/FileRecordingProcessor.cpp
<fc.T...... core/Pipeline.hpp
...

Number of files: 4,910 (reg: 4,401, dir: 509)
Number of created files: 0
Number of regular files transferred: 35
Total file size: 332.34M bytes
Total transferred file size: 2.62M bytes
Literal data: 0 bytes
Matched data: 2.62M bytes
File list size: 196.59K
File list generation time: 0.457 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 209.72K
Total bytes received: 12.03K

sent 209.72K bytes  received 12.03K bytes  147.83K bytes/sec
total size is 332.34M  speedup is 1,498.70

即使本地没有任何变化,rsync 也会在每次调用时传输相同的文件(子)集。

这些文件只是整个树的一小部分。其他文件除非确实发生更改,否则不会重新发送。重新发送的文件数始终为 35 个。所有文件都有<fc.T......标志。

文件在本地和远程机器上看起来完全相同。

当地的:

$ ll core/Pipeline.hpp
-rw-r--r-- 1 victor victor 5.1K Nov  2 18:24 core/Pipeline.hpp
$ md5sum core/Pipeline.hpp
7604940d777322a587d2fe2fa12c1183  core/Pipeline.hpp

偏僻的:

$ ll core/Pipeline.hpp
-rw-r--r-- 1 victor staff 5.1K Nov  3 18:20 core/Pipeline.hpp
$ md5sum core/Pipeline.hpp
7604940d777322a587d2fe2fa12c1183  core/Pipeline.hpp

所有者、组和时间不一样,但 rsync 未配置为保留它们,而是配置为使用校验和

两台机器的时间不同步。

答案1

发生这种情况的一种情况是当 rsync 在区分大小写的文件系统(通常是 Linux)和不区分大小写的文件系统(通常是 Windows 和 MacOS)之间传输文件时。

如果同步的两个路径(例如d/xd/X)在名义上转换为小写之后相同,则 rsync 不会注意到,并且可能会传输d/x,然后用覆盖相同的目标文件d/X

如果文件不包含相同的数据,但具有相同的时间戳,则文件将在未来 rsync 运行时始终更新。

我建议检查一下大小写差异是否导致 rsync 错误地重新传输文件。一个有用的 Linux 命令是:

find . | tr '[:upper:]' '[:lower:]' | LC_ALL=C sort | LC_ALL=C uniq -d

来源

答案2

您缺少--archive( -a) 或--times( -t) 标志。如果没有其中一个,rsync则不会跟踪更改时间,因此无法绕过看起来已被复制的文件

您还明确告知rsync使用校验和来验证文件是否已被复制,所以这就是所做的rsync

一般来说,--archive( -a) 标志几乎可以满足您的所有需求:

rsync --exclude FOO --exclude BAR -avi --delete --stats /local/dir/ host:/remote/dir/

您可能需要添加-H以保留硬链接(如果有),以及-AX保留 ACL 和扩展属性(如果有)。

答案3

TL;DR:如果您使用的是 macOS,请尝试使用 /usr/bin/rsync,而不是“brew”或“nix”或其他系统可能安装的开源 rsync。本机 rsync 更好地理解 Apple 的特殊文件系统,并且不会重新复制未更改的文件。

较长的版本...

如果您使用的版本不支持特定于操作系统的情况,则可能会发生这种情况rsync。它将重新复制它认为已更改但实际上没有更改的文件。

例如,我的 Mac 有两个版本rsync

$ which -a rsync
/usr/local/bin/rsync
/usr/bin/rsync

/usr/local/bin/rsync是版本 3.2.4,支持协议版本 31。我使用“brew”安装了它。

/usr/bin/rsync是 Apple 提供的版本,它是从 2.6.9 版本(更旧)分叉而来的,并支持协议版本 29。Apple 对此版本进行了增强,以支持特定于 macOS 的文件系统功能。

当我使用-c开源版本时,会重新复制未更改的文件。Apple 提供的 rsync 没有这个问题。

虽然协议版本 29 和 31 之间有很多优化,但您可能不会错过它们。使用 Apple 的 rsync 确保一切正确可能很重要。

答案4

我最终切换到齐奏用于 Linux 和 macOS(以及 Windows)之间的同步:

unison \
    -servercmd /usr/local/bin/unison
    -ignore "Name FOO" \
    -ignore "Name BAR" \
    -auto \
    -batch \
    -force /local/dir/ \
    /local/dir/ \
    ssh://host/remote/dir/

相关内容