Bisync

Bisync

bisync 目前处于 测试版,被视为 高级命令,因此使用时需谨慎。 在使用之前,请确保你已经阅读并理解了整个 手册(特别是 限制 部分),否则可能会导致数据丢失。如有问题,可在 Rclone 论坛 提问。

入门指南

  • 安装 rclone 并设置你的远程存储。
  • Bisync 会在不同系统上创建其工作目录:
    • 在 Linux 系统上,路径为 ~/.cache/rclone/bisync
    • 在 Mac 系统上,路径为 /Users/yourusername/Library/Caches/rclone/bisync
    • 在 Windows 系统上,路径为 C:\Users\MyLogin\AppData\Local\rclone\bisync。 请确保该位置可写。
  • 使用 --resync 标志运行 bisync 命令,并指定本地和远程同步目录的根路径。
  • 后续的同步运行中,请去掉 --resync 标志。(重要!
  • 考虑使用 过滤文件 来排除同步过程中不必要的文件和目录。
  • 为了安全起见,考虑设置 –check-access 功能。
  • 在 Linux 或 Mac 系统上,考虑设置 crontab 条目。由于 bisync 会维护锁文件,因此它可以在并发的 cron 作业中安全运行。

例如,你的第一条命令可能如下所示:

rclone bisync remote1:path1 remote2:path2 --create-empty-src-dirs --compare size,modtime,checksum --slow-hash-sync-only --resilient -MvP --drive-skip-gdocs --fix-case --resync --dry-run

如果一切正常,请在不使用 --dry-run 的情况下再次运行。 之后,再删除 --resync

以下是典型的运行日志(为清晰起见,删除了时间戳):

rclone bisync /testdir/path1/ /testdir/path2/ --verbose
INFO  : Synching Path1 "/testdir/path1/" with Path2 "/testdir/path2/"
INFO  : Path1 checking for diffs
INFO  : - Path1    File is new                         - file11.txt
INFO  : - Path1    File is newer                       - file2.txt
INFO  : - Path1    File is newer                       - file5.txt
INFO  : - Path1    File is newer                       - file7.txt
INFO  : - Path1    File was deleted                    - file4.txt
INFO  : - Path1    File was deleted                    - file6.txt
INFO  : - Path1    File was deleted                    - file8.txt
INFO  : Path1:    7 changes:    1 new,    3 newer,    0 older,    3 deleted
INFO  : Path2 checking for diffs
INFO  : - Path2    File is new                         - file10.txt
INFO  : - Path2    File is newer                       - file1.txt
INFO  : - Path2    File is newer                       - file5.txt
INFO  : - Path2    File is newer                       - file6.txt
INFO  : - Path2    File was deleted                    - file3.txt
INFO  : - Path2    File was deleted                    - file7.txt
INFO  : - Path2    File was deleted                    - file8.txt
INFO  : Path2:    7 changes:    1 new,    3 newer,    0 older,    3 deleted
INFO  : Applying changes
INFO  : - Path1    Queue copy to Path2                 - /testdir/path2/file11.txt
INFO  : - Path1    Queue copy to Path2                 - /testdir/path2/file2.txt
INFO  : - Path2    Queue delete                        - /testdir/path2/file4.txt
NOTICE: - WARNING  New or changed in both paths        - file5.txt
NOTICE: - Path1    Renaming Path1 copy                 - /testdir/path1/file5.txt..path1
NOTICE: - Path1    Queue copy to Path2                 - /testdir/path2/file5.txt..path1
NOTICE: - Path2    Renaming Path2 copy                 - /testdir/path2/file5.txt..path2
NOTICE: - Path2    Queue copy to Path1                 - /testdir/path1/file5.txt..path2
INFO  : - Path2    Queue copy to Path1                 - /testdir/path1/file6.txt
INFO  : - Path1    Queue copy to Path2                 - /testdir/path2/file7.txt
INFO  : - Path2    Queue copy to Path1                 - /testdir/path1/file1.txt
INFO  : - Path2    Queue copy to Path1                 - /testdir/path1/file10.txt
INFO  : - Path1    Queue delete                        - /testdir/path1/file3.txt
INFO  : - Path2    Do queued copies to                 - Path1
INFO  : - Path1    Do queued copies to                 - Path2
INFO  : -          Do queued deletes on                - Path1
INFO  : -          Do queued deletes on                - Path2
INFO  : Updating listings
INFO  : Validating listings for Path1 "/testdir/path1/" vs Path2 "/testdir/path2/"
INFO  : Bisync successful

命令行语法

$ rclone bisync --help
Usage:
  rclone bisync remote1:path1 remote2:path2 [flags]

Positional arguments:
  Path1, Path2  Local path, or remote storage with ':' plus optional path.
                Type 'rclone listremotes' for list of configured remotes.

Optional Flags:
      --backup-dir1 string                   --Path1 的备份目录。必须是同一远程存储上不重叠的路径。
      --backup-dir2 string                   --Path2 的备份目录。必须是同一远程存储上不重叠的路径。
      --check-access                         确保在 Path1 和 Path2 文件系统中都能找到预期的 RCLONE_TEST 文件,否则中止操作。
      --check-filename string                --check-access 使用的文件名(默认值:RCLONE_TEST)
      --check-sync string                    控制最终列表的比较方式:true|false|only(默认值:true)
      --compare string                       以逗号分隔的 bisync 特定比较选项列表,例如 'size,modtime,checksum'(默认值:'size,modtime')
      --conflict-loser ConflictLoserAction   对同步冲突的“输家”(当有“赢家”时)或两个文件(当没有“赢家”时)采取的操作:, num, pathname, delete(默认值:num)
      --conflict-resolve string              通过优先选择以下版本来自动解决冲突:none, path1, path2, newer, older, larger, smaller(默认值:none)
      --conflict-suffix string               重命名 --conflict-loser 时使用的后缀。可以是一个字符串,也可以是两个用逗号分隔的字符串,分别为 Path1/Path2 指定不同的后缀。(默认值:'conflict')
      --create-empty-src-dirs                同步空目录的创建和删除操作。(与 --remove-empty-dirs 不兼容)
      --download-hash                        当无法获取哈希值时,通过下载文件来计算哈希值。(警告:可能会很慢,并且会消耗大量数据!)
      --filters-file string                  从文件中读取过滤模式
      --force                                绕过 --max-delete 安全检查并运行同步操作。建议与 --verbose 一起使用
  -h, --help                                 显示 bisync 命令的帮助信息
      --ignore-listing-checksum              不使用校验和来生成列表(添加 --ignore-checksum 可额外跳过复制后校验和检查)
      --max-lock Duration                    认为超过此时间的锁文件已过期(默认值:0(永不过期))(最小值:2 分钟)
      --no-cleanup                           保留工作文件(对于故障排除和测试很有用)。
      --no-slow-hash                         仅在计算校验和较慢的后端上忽略列表校验和
      --recover                              自动从中断中恢复,无需使用 --resync。
      --remove-empty-dirs                    在最后清理步骤中删除所有空目录。
      --resilient                            允许未来的运行在某些不太严重的错误后重试,而不是需要 --resync。使用时请自行承担风险!
  -1, --resync                               执行重新同步操作。等同于 --resync-mode path1。建议先使用 --verbose 或 --dry-run。
      --resync-mode string                   在重新同步期间,优先选择以下版本:path1, path2, newer, older, larger, smaller(默认值:如果使用 --resync 则为 path1,否则为 none 表示不进行重新同步)
      --retries int                          操作失败时重试的次数(需要 --resilient)。(默认值:3)
      --retries-sleep Duration               操作失败时重试的间隔时间,例如 500ms、60s、5m(0 表示禁用)(默认值:0s)
      --slow-hash-sync-only                  忽略列表和差异中的慢速校验和,但在同步调用期间仍考虑它们。
      --workdir string                       使用自定义工作目录 - 对于测试很有用。(默认值:{WORKDIR})
      --max-delete PERCENT                   允许删除文件的最大百分比安全检查。如果超过此百分比,bisync 运行将中止。(默认值:50%)
  -n, --dry-run                              模拟操作 - 不复制/删除任何文件。
  -v, --verbose                              增加日志详细程度。可以多次指定以获取更多详细信息。

可以在 bisync 命令行 中指定任意的 rclone 标志,例如: rclone bisync ./testdir/path1/ gdrive:testdir/path2/ --drive-skip-gdocs -v -v --timeout 10s 请注意,各种 rclone 标志与 bisync 流程的交互尚未经过全面测试。

路径

Path1 和 Path2 参数可以引用任何本地目录路径(绝对或相对)、UNC 路径(//server/share/path)、 Windows 驱动器路径(带驱动器盘符和 :)或已配置的 远程存储,并可选择指定子目录路径。 云存储引用的参数中会包含 :(请参阅下面的 Windows 支持)。

Path1 和 Path2 被同等对待,在文件更改方面两者都没有优先级(除了在使用 --resync 时),并且无论远程存储是在 Path1 还是 Path2 上,访问效率都不会改变。

bisync 工作目录(默认:~/.cache/rclone/bisync)中的列表文件根据 Path1 和 Path2 参数命名,这样可以设置对树中各个目录的单独同步,例如: path_to_local_tree..dropbox_subdir.lst

同步后,Path1 和 Path2 文件系统中的空目录默认不会被删除,除非指定了 --create-empty-src-dirs 标志。 如果指定了 --remove-empty-dirs 标志,那么在同步过程的最后一步,两个路径下的所有空目录都将被清除。

命令行标志

–resync

此标志将使 Path1 和 Path2 文件系统都包含所有文件的匹配超集。默认情况下,Path1 中不存在的 Path2 文件将被复制到 Path1,然后再将 Path1 中的文件树复制到 Path2。

--resync 操作流程大致等同于以下步骤(但请参阅 --resync-mode 以了解其他选项):

rclone copy Path2 Path1 --ignore-existing [--create-empty-src-dirs]
rclone copy Path1 Path2 [--create-empty-src-dirs]

Path1 和 Path2 文件系统中的基础目录必须存在,否则 bisync 会运行失败。这是一项安全要求,确保 bisync 能够验证两个路径都是有效的。

使用 --resync 时,Path2 文件系统中较新的文件版本(默认情况下)将被 Path1 文件系统中的版本覆盖。 (请注意,这并非完全对称,可以使用 --resync-mode 标志指定更对称的选项。)请使用 –dry-run 仔细评估差异。

在进行重新同步操作时,其中一个路径可以为空(路径树中没有文件)。重新同步操作应确保两个路径上都有文件,否则正常的非重新同步运行将失败。

对于非重新同步运行,如果任何一个路径为空(路径树中没有文件),则会出现错误 Empty current PathN listing. Cannot sync to an empty directory: X.pathN.lst。这是一项安全检查,防止意外的空路径导致删除另一个路径中的所有内容

请注意,除非明确指定了不同的 --resync-mode,否则 --resync 意味着 --resync-mode path1。不需要同时使用 --resync--resync-mode 标志,使用其中一个即可。

注意--resync(包括 --resync-mode)仅应在三种特定(罕见)情况下使用:

  1. 这是你(在这两个路径之间)的首次 bisync 运行。
  2. 你刚刚更改了 bisync 设置(例如编辑了 --filters-file 的内容)。
  3. 上一次运行出现错误,因此 bisync 现在需要 --resync 来恢复。

在其他时间,你应该省略 --resync。原因是 --resync 只会将每一侧的文件复制(而非同步)到另一侧。因此,如果你每次 bisync 运行都使用 --resync,那么就永远无法删除文件 —— 被删除的文件会在每次运行结束时重新出现(因为它会从另一侧仍然存在的地方被复制过来)。同样,重命名文件也会导致两侧都出现重复的副本(旧名称和新名称)。

如果你发现情况 3 中频繁的中断是个问题,建议不要自动运行 --resync,而是使用 --resilient--recover--conflict-resolve 标志(必要时结合优雅关机模式),以实现一个非常强大的 “设置后无需干预” 的 bisync 配置,几乎可以自动从任何可能遇到的中断中恢复。可以考虑添加如下内容:

--resilient --recover --max-lock 2m --conflict-resolve newer

–resync-mode 选项

在执行 --resync 操作时,如果某个文件在两侧存在差异,--resync-mode 用于控制哪一个版本将覆盖另一个版本。支持的选项与 --conflict-resolve 类似。对于以下所有选项,被保留的版本称为“赢家”,被覆盖(删除)的版本称为“输家”。这些选项以“赢家”命名:

  • path1 -(默认值) - 无条件地将 Path1 中的版本视为赢家(无论 modtimesize 如何)。当在执行 --resync 时,某一侧更值得信赖或更新时,此选项会很有用。
  • path2 - 与 path1 类似,只不过将 Path2 中的版本视为赢家。
  • newer - 将较新的文件(按 modtime 计算)视为赢家,无论它来自哪一侧。这可能会导致赢家同时来自 Path1 和 Path2。(其实现类似于双向运行 rclone copy --update。)
  • older - 与 newer 类似,只不过将较旧的文件视为赢家,较新的文件视为输家。
  • larger - 将较大的文件(按 size 计算)视为赢家(无论 modtime 如何)。对于不支持 modtime 的远程存储,或者对于那些随着时间推移通常会增大而不会缩小的文件(如日志文件),这是一个有用的选项。
  • smaller - 将较小的文件(按 size 计算)视为赢家(无论 modtime 如何)。

对于上述所有选项,请注意以下几点:

  • 如果底层的任何一个远程存储不支持所选的方法,该方法将被忽略,并回退到默认的 path1。(例如,如果设置了 --resync-mode newer,但其中一个路径使用的远程存储不支持 modtime。)
  • 如果由于所选方法的属性缺失或相等而无法确定赢家,该方法将被忽略,然后 bisync 会尝试通过查看其他生效的 --compare 方法来确定文件是否不同。(例如,如果设置了 --resync-mode newer,但 Path1 和 Path2 的 modtime 相同,bisync 会比较文件大小。)如果 bisync 得出它们不同的结论,则优先考虑此时作为“源”的一方。(实际上,这会给 Path2 带来一点优势,因为从 2 到 1 的复制操作在从 1 到 2 的复制操作之前进行。)如果文件没有不同,则不进行复制(因为两侧已经一致)。
  • 这些选项仅适用于在两侧都存在(具有相同名称和相对路径)的文件。在 --resync 期间,仅存在于一侧而不存在于另一侧的文件始终会被复制到另一侧(这是重新同步和非重新同步运行的主要区别之一)。
  • --conflict-resolve--conflict-loser--conflict-suffix--resync 期间不适用,与这些标志不同,--resync 期间不会重命名任何文件。当在 --resync 期间某个文件在两侧不同时,一个版本总是会覆盖另一个版本(就像在 rclone copy 中一样)。(可以考虑使用 --backup-dir 来保留输家版本的备份。)
  • --conflict-resolve 不同,--resync-mode none 不是一个有效的选项(或者说,它将被解释为“不进行重新同步”,除非同时指定了 --resync,在这种情况下它将被忽略)。
  • 赢家和输家仅在单个文件级别上确定(目前没有选项可以原子性地选择整个获胜目录,尽管 path1path2 选项通常会产生类似的结果)。
  • 为了保持向后兼容性,除非明确指定了不同的 --resync-mode,否则 --resync 标志意味着 --resync-mode path1。同样,所有 --resync-mode 选项(除了 none)都意味着 --resync,因此无需同时使用 --resync--resync-mode 标志 —— 使用其中一个就足够了。

–check-access

访问检查文件是防止数据丢失的额外安全措施。bisync 会确保在 Path1 和 Path2 文件系统的相同位置找到匹配的 RCLONE_TEST 文件。

RCLONE_TEST 文件不会自动生成。为了使 --check-access 检查成功,你必须首先执行以下操作之一: A) 在两个系统中都放置一个或多个 RCLONE_TEST 文件; B)--check-filename 设置为在整个同步文件集中各个位置已经使用的文件名。

推荐的执行 A) 的方法包括:

  • rclone touch Path1/RCLONE_TEST(创建一个新文件)
  • rclone copyto Path1/RCLONE_TEST Path2/RCLONE_TEST(复制一个现有文件)
  • rclone copy Path1/RCLONE_TEST Path2/RCLONE_TEST --include "RCLONE_TEST"(递归地一次性复制多个文件)
  • 手动创建文件(在 rclone 之外)
  • 不使用 --check-access 运行一次 bisync,在两个文件系统上设置匹配的文件。不过,由于存在用户操作失误的可能性,这种方法不太推荐(你暂时禁用了安全功能)。

请注意,--check-access--resync 时仍然会强制执行,因此 bisync --resync --check-access 不能作为初始设置文件的方法(这是为了确保 bisync 不会意外绕过其自身的安全开关)。

RCLONE_TEST 文件的时间戳和文件内容并不重要,重要的只是文件名和位置。如果你的同步树中存在符号链接,建议将 RCLONE_TEST 文件放置在链接指向的目录树中,以防止在链接指向的树不可访问时,bisync 误判为大量文件被删除。

另请参阅 –check-filename 标志。

–check-filename

用于访问健康验证的文件名称。

默认的 --check-filenameRCLONE_TEST。为了使 --check-access 检查成功,必须存在一个或多个具有此文件名的文件,并且这些文件在源文件集和目标文件集之间是同步的。

有关更多详细信息,请参阅 –check-access

–compare

v1.66 版本开始,bisync 完全支持基于大小、修改时间和校验和的任意组合进行比较(解除了之前对不支持修改时间的后端的限制)。

默认情况下(不使用 --compare 标志),bisync 继承与 sync 相同的比较选项(即:默认情况下比较 sizemodtime,除非使用诸如 --checksum--size-only 等标志进行修改)。

如果设置了 --compare 标志,它将覆盖这些默认值。如果你希望基于 sync 目前不支持的组合进行比较,例如同时比较 sizemodtimechecksum 这三个值(或者仅比较 modtimechecksum),这将非常有用。

--compare 接受一个逗号分隔的列表,目前支持的值为 sizemodtimechecksum。例如,如果你想比较大小和校验和,但不比较修改时间,可以这样做:

--compare size,checksum

或者,如果您想将三者进行比较:

--compare size,modtime,checksum

[]: # … existing code …

--compare 会覆盖任何冲突的标志。例如,如果你设置了冲突的标志 --compare checksum --size-only--size-only 将被忽略,bisync 会比较校验和而不是文件大小。为避免混淆,建议仅使用 --compare 或常规的 sync 标志,不要同时使用两者。

如果 --compare 包含 checksum,并且两个远程存储都支持校验和,但它们没有共同的哈希类型,那么校验和将仅用于同一侧的比较(以确定自上次同步以来有哪些更改),而不会用于与另一侧的比较。如果一侧支持校验和,而另一侧不支持,则仅在支持校验和的一侧考虑校验和。

当使用 checksum 和/或 size 进行比较而不使用 modtime 时,bisync 无法确定文件是 newer 还是 older,只能确定它是 changed 还是 unchanged。(如果文件在两侧都 changedbisync 仍会进行标准的相等性检查,除非绝对必要,否则不会宣布同步冲突。)

建议在更改 --compare 设置时执行 --resync,否则之前的列表文件可能不包含你希望比较的属性(例如,如果你之前没有比较校验和,它们就不会存储校验和)。

–ignore-listing-checksum

当设置了 --checksum--compare checksum 时,bisync 在为两个路径创建列表时会获取(或生成)校验和(对于支持校验和的后端),并将校验和存储在列表文件中。--ignore-listing-checksum 将禁用此行为,这可能会显著加快速度,特别是在那些必须动态计算哈希而不是直接获取的后端(如 本地)上。请注意以下几点:

  • v1.66 版本开始,当 --checksum--compare checksum 都未使用时,--ignore-listing-checksum 会自动设置(因为此时校验和不会被使用)。
  • --ignore-listing-checksum--ignore-checksum 不同,你可以选择使用其中一个或两个都使用。简而言之:--ignore-listing-checksum 控制在扫描差异时是否考虑校验和,而 --ignore-checksum 控制在后续的复制/同步操作中(如果检测到差异)是否考虑校验和。
  • 除非传递了 --ignore-listing-checksum,否则 bisync 目前会为一个路径计算哈希值,即使与另一个路径没有共同的哈希类型(例如,一个 加密 远程存储)。这仍然是有益的,因为即使哈希值不能用于与另一侧进行比较,它们仍可用于检测同一侧的更改(如果设置了 --checksum--compare checksum)。
  • 如果你只想在计算校验和较慢的远程存储上忽略列表校验和,可以考虑使用 --no-slow-hash(或 --slow-hash-sync-only),而不是 --ignore-listing-checksum
  • 如果 --ignore-listing-checksum--compare checksum(或 --checksum)同时使用,校验和将在 bisync 计算差异时被忽略,但在后续的同步操作中(如果基于修改时间和/或文件大小检测到差异)仍会被考虑。

–no-slow-hash

在某些远程存储(特别是 local)上,校验和会显著减慢 bisync 运行速度,因为哈希值无法存储,需要在请求时实时计算。而在其他远程存储(如 drive)上,计算校验和几乎不会增加时间。--no-slow-hash 标志会自动跳过计算校验和较慢的远程存储上的校验和,同时仍会在其他远程存储上进行比较(假设 --compare 包含 checksum)。当你的 bisync 路径中有一个速度较慢,但你仍希望在另一个路径上检查校验和以实现更可靠的同步时,这个标志会很有用。

–slow-hash-sync-only

--no-slow-hash 相同,只是在同步调用期间仍会考虑计算较慢的哈希值。它们仍不会用于确定差异,也不会包含在列表中。在 --resync 期间也会跳过它们。此标志的主要使用场景是当你有大量文件,但每次运行时更改的文件相对较少时——你不想每次都检查整个文件树(这会花费太长时间),但仍希望对检测到修改时间或文件大小有变化的较小文件组考虑校验和。请记住,这种速度提升是以牺牲安全性为代价的:如果文件内容发生更改而其修改时间或文件大小没有变化,bisync 将无法检测到,并且不会进行同步。

--slow-hash-sync-only 仅在两个远程存储共享共同的哈希类型时才有用(如果没有,bisync 将自动回退到 --no-slow-hash)。如果没有 --compare checksum(或 --checksum),--no-slow-hash--slow-hash-sync-only 都不会起作用。

–download-hash

如果设置了 --download-hash,当校验和无法以其他方式获取时(例如,远程存储不支持校验和),bisync 将尽力通过下载文件并实时计算来获取 MD5 校验和。请注意,由于 rclone 必须下载整个文件,这可能会显著减慢 bisync 运行速度,并且可能会消耗大量数据,因此对于总文件大小较大的 bisync 路径来说,这可能不太实际。然而,对于以最高精度同步小而重要的文件(例如,crypt 远程存储上的源代码仓库),这可能是一个不错的选择。与 cryptcheck 等方法相比,额外的优势是不需要原始文件进行比较(例如,--download-hash 可用于对两个使用不同密码的不同加密远程存储进行双向同步)。

当设置了 --download-hash 时,bisync 仍会首先查找更高效的校验和,只有在找不到时才会回退到下载文件。它优先于 --no-slow-hash 等冲突标志。--download-hash 不适用于 Google Docs 和其他大小未知的文件,因为它们的校验和会在每次运行时发生变化(由于生成的导出文件内部存在细微差异)。因此,bisync 会自动跳过对大小小于 0 的文件使用 --download-hash

另请参阅:Hasher 后端、cryptcheck 命令、rclone check --download 选项、md5sum 命令

–max-delete

作为一项安全检查,如果在 Path1 或 Path2 文件系统中删除的文件百分比超过 --max-delete 设置的值,bisync 将中止并发出警告消息,不会进行任何更改。默认的 --max-delete 值是 50%。触发此限制的一种情况是重命名一个包含超过一半文件的目录。这对 bisync 来说相当于删除了一堆文件并添加了一堆新文件。

此安全检查旨在防止 bisync 由于临时网络访问问题或用户意外删除了一侧的文件而删除两个文件系统上的所有文件。要强制进行同步,可以设置不同的删除百分比限制,例如 --max-delete 75(允许最多删除 75% 的文件),或者使用 --force 绕过此检查。

另请参阅 所有文件更改 检查。

–filters-file

通过使用 rclone 的过滤功能,你可以在同步过程中排除某些文件类型或目录子树。 请参阅 双向同步过滤 部分和通用的 –filter-from 文档。 示例过滤文件 包含了与 Dropbox 同步时不允许的文件的过滤规则。

如果你对过滤文件进行了更改,则 bisync 需要使用 --resync 进行一次运行。这是一项安全功能,可防止 Path1 和/或 Path2 上的现有文件看似消失(因为它们在新的列表中被排除),从而避免 bisync 误以为它们已被删除(与之前的运行列表相比),进而实际删除这些文件。

为了防止这种情况发生,bisync 会计算过滤文件的 MD5 哈希值,并将该哈希值存储在与过滤文件相同位置的 .md5 文件中。在下一次设置了 --filters-file 的运行中,bisync 会重新计算当前过滤文件的 MD5 哈希值,并将其与 .md5 文件中存储的哈希值进行比较。如果它们不匹配,运行将以严重错误中止,从而迫使你执行 --resync,可能避免一场灾难。

–conflict-resolve 选择

bisync 中,“冲突” 是指在 两侧(相对于上一次运行)新出现已更改当前两侧不相同 的文件。--conflict-resolve 控制 bisync 如何处理这种情况。目前支持的选项有:

  • none -(默认值) - 不尝试选择获胜者,根据 --conflict-loser--conflict-suffix 设置保留并重命名两个文件。例如,在默认设置下,Path1 上的 file.txt 将被重命名为 file.txt.conflict1,Path2 上的 file.txt 将被重命名为 file.txt.conflict2。在运行过程中,两个文件都会被复制到另一侧,因此两侧最终都会有两个文件的副本。(由于 none 是默认值,因此无需指定 --conflict-resolve none,可以直接省略该标志。)
  • newer - 较新的文件(按 modtime 计算)被视为获胜者,会被复制且不重命名。较旧的文件(“输家”)将根据 --conflict-loser--conflict-suffix 设置进行处理(要么重命名,要么删除)。例如,如果 Path1 上的 file.txt 比 Path2 上的 file.txt 新,那么在两侧(在其他默认设置下)的结果将是 file.txt(来自 Path1 的获胜者)和 file.txt.conflict1(来自 Path2 的输家)。
  • older - 与 newer 相同,只是较旧的文件被视为获胜者,较新的文件被视为输家。
  • larger - 较大的文件(按 size 计算)被视为获胜者(无论 modtime 如何)。对于不支持 modtime 的远程存储,或者对于那些随着时间推移通常会增大而不会缩小的文件(如日志文件),这是一个有用的选项。
  • smaller - 较小的文件(按 size 计算)被视为获胜者(无论 modtime 如何)。
  • path1 - 无条件地将 Path1 中的版本视为获胜者(无论 modtimesize 如何)。当一侧通常比另一侧更可信或更新时,此选项会很有用。
  • path2 - 与 path1 类似,只不过将 Path2 中的版本视为获胜者。

对于上述所有选项,请注意以下几点:

  • 如果底层的任何一个远程存储不支持所选的方法,该方法将被忽略,并回退到 none。(例如,如果设置了 --conflict-resolve newer,但其中一个路径使用的远程存储不支持 modtime。)
  • 如果由于所选方法的属性缺失或相等而无法确定获胜者,该方法将被忽略,然后回退到 none。(例如,如果设置了 --conflict-resolve newer,但 Path1 和 Path2 的修改时间相同,即使文件大小可能不同。)
  • 如果文件的内容在两侧当前相同,即使自上次同步以来在两侧都是新的或已更改的,也不认为是 “冲突”。(例如,如果你在一侧进行了更改,然后通过其他方式将其同步到了另一侧。)因此,在这种情况下,所有冲突解决标志都不适用。
  • 冲突解决标志在 --resync 期间不适用,因为在 --resync 时没有 “上一次运行” 的概念(但请参阅 --resync-mode 以获取类似的选项)。

–conflict-loser 选择

--conflict-loser 确定在同步冲突中 “输家”(当 --conflict-resolve 确定了获胜者时)或两个文件(当没有获胜者时)的处理方式。目前支持的选项有:

  • num -(默认值) - 按时间顺序自动为冲突编号,将下一个可用的数字附加到 --conflict-suffix 后面。例如,在默认设置下,file.txt 的第一个冲突将被重命名为 file.txt.conflict1。如果 file.txt.conflict1 已经存在,则将使用 file.txt.conflict2 等(最多可达 9223372036854775807 个冲突)。
  • pathname - 根据文件来自哪一侧对冲突进行重命名,这是 v1.66 之前的默认行为。例如,使用 --conflict-suffix path,来自 Path1 的 file.txt 将被重命名为 file.txt.path1,来自 Path2 的 file.txt 将被重命名为 file.txt.path2。如果提供了两个不同的后缀(例如 --conflict-suffix cloud,local),则省略尾随数字。重要的是要注意,使用 pathname 时,除了 2 之外没有自动编号,因此如果 file.txt.path2 已经存在,它将被覆盖。在 --conflict-suffix 中使用动态日期变量(见下文)是避免这种情况的一种可能方法。还要注意,如果原始冲突没有手动解决,可能会出现冲突的冲突——例如,如果你出于某种原因在两侧都编辑了 file.txt.path1,并且这些编辑不同,结果将是 file.txt.path1.path1file.txt.path1.path2(除了 file.txt.path2)。
  • delete - 仅保留获胜者并删除输家,而不是重命名它。如果无法确定获胜者(有关这种情况如何发生的详细信息,请参阅 --conflict-resolve),delete 将被忽略,使用默认的 num(即保留并重命名两个版本,都不删除)。delete 本质上是最具破坏性的选项,因此请谨慎使用。

对于上述所有选项,请注意,如果无法确定获胜者(有关这种情况如何发生的详细信息,请参阅 --conflict-resolve),或者未使用 --conflict-resolve两个 文件都将被重命名。

–conflict-suffix 字符串[,字符串]

--conflict-suffix 控制 bisync 重命名 --conflict-loser 时附加的后缀(默认值:conflict)。--conflict-suffix 可以接受一个字符串或两个用逗号分隔的字符串,以便为 Path1 和 Path2 分配不同的后缀。这可能有助于稍后识别冲突的来源。(例如,--conflict-suffix dropboxconflict,laptopconflict

使用 --conflict-loser num 时,数字总是会附加到后缀后面。使用 --conflict-loser pathname 时,只有在指定了一个后缀(或两个相同的后缀)时才会附加数字。也就是说,使用 --conflict-loser pathname 时,以下所有设置都会产生完全相同的结果:

--conflict-suffix path
--conflict-suffix path,path
--conflict-suffix path1,path2

后缀可短至 1 个字符。 默认情况下,后缀 在任何其他扩展名之后(例如,file.jpg.conflict1),但可以使用 但是,可以使用 --suffix-keep-extension标记来更改。 (即改为file.conflict1.jpg)。

--conflict-suffix 支持多个动态日期变量。 大括号括起来时,支持多个动态日期变量。 这有助于跟踪 bisync 处理每个冲突的日期和/或时间。 例如

--conflict-suffix {DateOnly}-conflict
// result: myfile.txt.2006-01-02-conflict1

此处此处 描述的所有格式均受支持,但请务必确保你选择的格式不包含远程存储中非法的字符(例如,macOS 不允许文件名中包含冒号,并且最好避免使用斜杠,因为它们通常会被解释为目录分隔符)。为了解决这个特定问题,还支持 {MacFriendlyTime}(或简写成 {mac})选项,它会生成 2006-01-02 0304PM 这样的时间格式。

请注意,--conflict-suffix 与 rclone 的主要 --suffix 标志完全独立。这是有意为之的,因为如果同时使用 --backup-dir,用户可能希望同时使用这两个标志。

最后,请注意,在 v1.66 之前,bisync 默认使用 ..path1..path2 来重命名冲突文件(两个点,并且使用 path 而不是 conflict)。现在,bisync 默认使用单个点而不是双点,但可以通过在指定的后缀字符串中包含额外的点来添加更多点。例如,要实现与之前默认行为相同的效果,请使用:

[--conflict-resolve none] --conflict-loser pathname --conflict-suffix .path

–check-sync

check-sync 功能默认启用,它会检查 Path1 和 Path2 的历史列表中是否存在相同的文件。默认情况下,这个 check-sync 完整性检查会在同步运行结束时执行。

两个路径之间任何未被捕获的复制/删除失败操作,都可能导致两个列表之间出现差异,以及两个路径之间未跟踪的文件内容存在差异。执行重新同步操作可以纠正此错误。

请注意,默认启用的完整性检查会在本地加载最终的 Path1 和 Path2 列表,因此会增加同步运行的时间。使用 --check-sync=false 可以禁用此检查,对于大量文件的同步,这可能会显著减少同步运行时间。

可以使用 --check-sync=only 手动运行此检查。它只会运行完整性检查,然后终止,而不会实际进行同步。

请注意,目前 --check-sync 仅检查列表快照,而不检查远程存储上的实际文件。此外,列表快照不会反映最新的 bisync 运行期间或之后发生的任何更改,因为这些更改将在下一次运行时被发现。因此,虽然在 bisync 运行结束时,列表应该始终彼此匹配,但如果在运行期间或之后发生了更改,列表与底层远程存储不匹配,或者远程存储之间不匹配,这是正常现象。任何差异将在下一次运行时被检测到并同步。

要对远程存储的当前状态进行可靠的完整性检查(而不仅仅是它们的列表快照),可以考虑使用 check(如果至少有一个路径是 crypt 远程存储,则使用 cryptcheck),而不是 --check-sync,同时要记住,如果在上次 bisync 运行期间或之后文件发生了更改,出现差异是正常的。

例如,一个可能的操作序列如下:

  1. 正常调度的 bisync 运行:
rclone bisync Path1 Path2 -MPc --check-access --max-delete 10 --filters-file /path/to/filters.txt -v --no-cleanup --ignore-listing-checksum --disable ListR --checkers=16 --drive-pacer-min-sleep=10ms --create-empty-src-dirs --resilient
  1. 定期进行独立的完整性检查(可能每晚或每周一次):
rclone check -MvPc Path1 Path2 --filter-from /path/to/filters.txt
  1. 如果发现差异,您可以选择纠正它们。 如果一方更新较快,而你想让另一方与之相匹配,你可以运行:
rclone sync Path1 Path2 --filter-from /path/to/filters.txt --create-empty-src-dirs -MPc -v

[]: # … existing code …

(或者交换 Path1 和 Path2,让 Path2 成为基准)

或者,如果两边都不是完全最新的,你可以运行 --resync 使它们重新达成一致 (但请记住,这可能会导致已删除的文件重新出现)。

  • 另请注意,rclone check 当前不包含空目录, 所以如果你想知道是否有任何空目录不同步, 可以考虑在上述 rclone sync 命令中添加 --dry-run 来运行。

另请参阅:并发修改--resilient

–resilient

注意:这是一个实验性特性。使用风险自负!

默认情况下,大多数错误或中断会导致 bisync 中止,并需要使用 --resync 来恢复。这是一项安全特性,目的是在用户检查情况之前阻止 bisync 再次运行。然而,在某些情况下,bisync 可能反应过度,在实际上不需要锁定的情况下实施了锁定,例如某些不太严重的错误,这些错误可能会在下一次运行时自行解决。当指定 --resilient 时,bisync 会尽力恢复并自我纠正,只有在绝对需要人工干预时才会要求使用 --resync。其预期使用场景是将 bisync 作为后台进程运行(例如通过定时 cron 任务)。

在使用 --resilient 模式时,bisync 仍然会报告错误并中止,但不会锁定后续运行 —— 这允许在下次正常调度的时间重试,而无需先使用 --resync。此类可重试错误的示例包括访问测试失败、缺少列表文件和检测到过滤规则更改。这些安全特性仍会阻止当前运行继续进行 —— 不同之处在于,如果到下一次运行时条件有所改善,那么下一次运行将被允许继续。某些更严重的错误即使在 --resilient 模式下也会强制使用 --resync 进行锁定,以防止数据丢失。

--resilient 的行为在未来版本中可能会发生变化。(另请参阅:--recover--max-lock优雅关闭

–recover

如果设置了 --recover,在突然中断或其他异常关闭的情况下,bisync 会在下次运行时尝试自动恢复,而不是要求使用 --resyncbisync 能够通过始终保留一个“备份”列表来进行可靠恢复,该列表代表了上次已知成功同步后两个路径的状态。然后,bisync 可以将当前状态与这个快照进行比较,以确定需要重试哪些更改。在这个快照之后(在后来被中断的运行期间)同步的更改,在 bisync 看来就像是“两边都有新更改或已更改”,但在大多数情况下这不是问题,因为 bisync 会进行常规的“相等性检查”,并发现这些文件在两边已经相同,无需采取任何操作。

在极少数情况下,如果一个文件在一次运行中成功同步,但在该运行中止后,在下一次运行之前再次发生更改,bisync 会认为这是一个同步冲突,并相应地进行处理。(从 bisync 的角度来看,自上次可信同步以来,该文件在两边都发生了更改,并且两边的文件当前并不相同。)因此,--recover 会稍微增加出现冲突的可能性 —— 不过在实践中这种情况相当罕见,因为导致这种情况的条件非常特殊。如果可以选择,使用 bisync“优雅关闭” 模式(通过发送 SIGINT 或按下 Ctrl+C 触发)而不是强制突然终止,可以降低这种风险。

--recover--resilient 相似但不同 —— 主要区别在于 --resilient 侧重于重试,而 --recover 侧重于恢复。大多数用户可能两者都需要。--resilient 允许在 bisync 由于安全特性(如 --check-access 失败或检测到过滤规则更改)而自行中止时进行重试。--resilient 不涵盖外部中断,例如用户在同步过程中关闭计算机 —— 这正是 --recover 的作用。

–max-lock

bisync 使用 锁文件 作为安全特性,以防止在运行时受到其他 bisync 运行的干扰。bisync 通常会在运行结束时删除这些锁文件,但如果 bisync 被突然中断,这些文件将被保留。默认情况下,它们会锁定所有未来的运行,直到用户有机会手动检查情况并删除锁。作为一种替代方法,可以使用 --max-lock 使它们在一段时间后自动过期,这样未来的运行就不会被永久锁定,并且可以进行自动恢复。--max-lock 可以是 2m 或更长的任何持续时间(或 0 以禁用)。如果设置了该选项,超过此时间的锁文件将被视为“过期”,未来的运行将被允许忽略它们并继续进行。(请注意,--max-lock 持续时间必须由留下锁文件的进程设置 —— 而不是后续解释它的进程。)

如果设置了该选项,bisync 还会在运行期间每隔 --max-lock 减去一分钟“更新”这些锁文件,以增加安全性。(例如,使用 --max-lock 5mbisync 会每隔 4 分钟更新一次锁文件(再延长 5 分钟),直到运行完成。)换句话说,在创建锁文件的进程仍在运行时,锁文件不应超过其过期时间 —— 因此,你可以合理地确定你发现的任何过期锁文件是由中断的运行留下的,而不是仍在运行只是耗时较长的运行留下的。

如果 --max-lock0 或未设置,默认情况下锁文件永远不会过期,并且会无限期地阻止未来的运行(针对相同的两个 bisync 路径)。

为了从中断中获得最大的恢复能力,可以考虑设置相对较短的持续时间,如 --max-lock 2m,同时使用 --resilient--recover,并设置相对频繁的 cron 调度。这样的结果将是一个非常可靠的“设置后无需干预”的 bisync 运行,它几乎可以从任何遇到的中断中自动恢复,而无需用户介入并运行 --resync。(另请参阅:优雅关闭 模式)

–backup-dir1 和 –backup-dir2

v1.66 版本开始,bisync 支持 --backup-dir。 由于 --backup-dir 必须是同一远程上不重叠的路径, bisync 引入了新的 --backup-dir1--backup-dir2 标志,以支持为 Path1Path2 设置单独的备份目录(否则使用 --backup-dir 在不同远程之间进行 bisync 是不可能的)。--backup-dir1--backup-dir2 可以使用彼此不同的远程,但 --backup-dir1 必须使用与 Path1 相同的远程,--backup-dir2 必须使用与 Path2 相同的远程。每个备份目录不得与其各自的 bisync 路径重叠,除非被过滤规则排除。

如果两个路径使用相同的远程,标准的 --backup-dir 也可以使用(但请注意,两个路径中删除的文件会混合在同一个目录中)。如果设置了 --backup-dir1--backup-dir2 中的任何一个,它们将覆盖 --backup-dir

示例:

rclone bisync /Users/someuser/some/local/path/Bisync gdrive:Bisync --backup-dir1 /Users/someuser/some/local/path/BackupDir --backup-dir2 gdrive:BackupDir --suffix -2023-08-26 --suffix-keep-extension --check-access --max-delete 10 --filters-file /Users/someuser/some/local/path/bisync_filters.txt --no-cleanup --ignore-listing-checksum --checkers=16 --drive-pacer-min-sleep=10ms --create-empty-src-dirs --resilient -MvP --drive-skip-gdocs --fix-case

在这个示例中,如果用户在 /Users/someuser/some/local/path/Bisync 中删除了一个文件,bisync 会将该删除操作同步到另一侧,即将 gdrive:Bisync 中对应的文件移动到 gdrive:BackupDir。如果用户从 gdrive:Bisync 中删除了一个文件,bisync 会将其从 /Users/someuser/some/local/path/Bisync 移动到 /Users/someuser/some/local/path/BackupDir

在发生因同步冲突而重命名的情况时,重命名操作不被视为删除,除非存在与相同名称的先前冲突且会被覆盖。

另请参阅:--suffix--suffix-keep-extension

操作

运行时流程细节

bisync 会保留上一次运行时 Path1Path2 文件系统的文件列表。 在每次后续运行时,它将执行以下操作:

  • 列出 path1path2 上的文件,并检查每一侧的更改。 更改包括 新文件更新的文件旧文件已删除的文件
  • path1 上的更改同步到 path2,反之亦然。

安全措施

  • 锁文件可防止在操作耗时较长时同时进行多次运行。 如果 bisync 由 cron 调度器运行,这一点尤为有用。
  • 根据 --conflict-resolve--conflict-loser--conflict-suffix 设置,以非破坏性方式处理更改冲突,创建 .conflict1.conflict2 等文件版本。
  • 使用 RCLONE_TEST 文件进行文件系统访问健康检查 (请参阅 --check-access 标志)。
  • 若删除操作过多则中止 - 防止将失败的文件列表解读为所有文件都已删除。 请参阅 --max-delete--force 标志。
  • 如果发生严重问题,bisync 会进入安全状态,以阻止后续运行造成损害。(请参阅 错误处理

正常同步检查

类型 描述 结果 实现方式
Path2 新文件 文件在 Path2 上是新的,在 Path1 上不存在 Path2 版本保留 rclone copy Path2 到 Path1
Path2 更新文件 文件在 Path2 上是更新的,在 Path1 上未更改 Path2 版本保留 rclone copy Path2 到 Path1
Path2 删除文件 文件在 Path2 上被删除,在 Path1 上未更改 文件被删除 rclone delete Path1
Path1 新文件 文件在 Path1 上是新的,在 Path2 上不存在 Path1 版本保留 rclone copy Path1 到 Path2
Path1 更新文件 文件在 Path1 上是更新的,在 Path2 上未更改 Path1 版本保留 rclone copy Path1 到 Path2
Path1 旧文件 文件在 Path1 上是旧的,在 Path2 上未更改 Path1 版本保留 rclone copy Path1 到 Path2
Path2 旧文件 文件在 Path2 上是旧的,在 Path1 上未更改 Path2 版本保留 rclone copy Path2 到 Path1
Path1 删除文件 文件在 Path1 上不再存在 文件被删除 rclone delete Path2

异常同步检查

类型 描述 结果 实现方式
Path1 新/更改 且 Path2 新/更改 且 Path1 == Path2 文件在 Path1 上是新的/已更改,在 Path2 上也是新的/已更改,并且 Path1 版本当前与 Path2 相同 无更改
Path1 新 且 Path2 新 文件在 Path1 上是新的,在 Path2 上也是新的(并且 Path1 版本与 Path2 不同) 根据 --conflict-resolve--conflict-loser 设置处理冲突 默认:rclone copy 重命名后的 Path2.conflict2 文件到 Path1,rclone copy 重命名后的 Path1.conflict1 文件到 Path2
Path2 更新 且 Path1 更改 文件在 Path2 上是更新的,在 Path1 上也有更改(更新/旧/大小不同)(并且 Path1 版本与 Path2 不同) 根据 --conflict-resolve--conflict-loser 设置处理冲突 默认:rclone copy 重命名后的 Path2.conflict2 文件到 Path1,rclone copy 重命名后的 Path1.conflict1 文件到 Path2
Path2 更新 且 Path1 删除 文件在 Path2 上是更新的,在 Path1 上被删除 Path2 版本保留 rclone copy Path2 到 Path1
Path2 删除 且 Path1 更改 文件在 Path2 上被删除,在 Path1 上有更改(更新/旧/大小不同) Path1 版本保留 rclone copy Path1 到 Path2
Path1 删除 且 Path2 更改 文件在 Path1 上被删除,在 Path2 上有更改(更新/旧/大小不同) Path2 版本保留 rclone copy Path2 到 Path1

rclone v1.64 版本开始,bisync 现在更善于检测误报同步冲突,这些冲突以前会导致不必要的重命名和重复文件。现在,当 bisync 遇到一个想要重命名的文件时(因为它在两侧都是新的/已更改的),它首先会检查 Path1 和 Path2 版本当前是否相同(使用与 check 相同的底层函数)。如果 bisync 得出文件相同的结论,它将跳过这些文件并继续处理。否则,它将像以前一样创建重命名的副本。 这种行为还改善了重命名目录的体验,因为只要在两侧都进行了相同的更改,就不再需要 --resync

所有文件更改检查

如果任一文件系统上的所有先前存在的文件都发生了更改(例如,由于更改系统时区导致时间戳发生变化),则 bisync 将在不进行任何更改的情况下中止。此检查不考虑任何新文件。你可以使用 --force 强制进行同步(时间戳文件发生更改的一侧获胜)。或者,可以使用 --resync(Path1 版本将被推送到 Path2)。在进行更改之前,请仔细考虑这种情况,并可能使用 --dry-run

修改时间

默认情况下,bisync 根据修改时间和大小比较文件。 如果你或你的应用程序在不更改修改时间和大小的情况下更改了文件内容,bisync不会检测到更改,因此不会将其复制到另一侧。 作为替代方案,考虑根据校验和进行比较(如果你的远程存储支持)。 有关详细信息,请参阅 --compare

错误处理

某些 bisync 严重错误,例如文件复制/移动失败,将导致后续运行被锁定。之所以进行锁定,是因为无法信任 Path1 和 Path2 文件系统的同步状态和历史记录,因此在有人检查情况之前,阻止任何进一步的更改更为安全。恢复方法是再次执行 --resync

建议最初使用 --resync --dry-run --verbose,并在不使用 --dry-run 运行 --resync 之前仔细审查将进行的更改。

大多数此类事件是由于内部调用返回错误状态引起的。在发生此类严重错误时,{...}.path1.lst{...}.path2.lst 文件列表将被重命名为扩展名 .lst-err,这将阻止任何未来的 bisync 运行(因为找不到正常的 .lst 文件)。bisync 将这些文件保存在 rclone 缓存目录的 bisync 子目录中,在 Linux 上通常位于 ${HOME}/.cache/rclone/bisync/

有些错误被认为是临时的,不会阻止重新运行 bisync严重返回将阻止进一步的 bisync 运行。

另请参阅:--resilient--recover--max-lock优雅关闭

锁文件

bisync 运行时,会在 bisync 工作目录中创建一个锁文件,在 Linux 上通常位于 ~/.cache/rclone/bisync/PATH1..PATH2.lck。如果 bisync 崩溃或挂起,锁文件将保留在原地,并阻止相同路径的任何进一步的 bisync 运行。在调试情况时,请删除锁文件。锁文件在先前的调用耗时较长时,有效地阻止后续(例如,由 cron 调度)运行。锁文件包含阻止进程的 PID,这可能有助于调试。可以使用 --max-lock 标志将锁文件设置为在一定时间后自动过期。

注意 虽然允许并发的 bisync 运行,但要非常谨慎,确保并发运行之间同步的目录树没有重叠,以免出现重复文件、删除文件和混乱情况。

退出代码

rclone bisync 向调用程序返回以下代码:

  • 运行成功返回 0
  • 非严重失败运行返回 1(重新运行可能成功),
  • 语法或使用错误返回 2
  • 严重中止运行返回 7(需要 --resync 进行恢复)。

另请参阅主文档中关于退出代码的部分。

优雅关闭

bisync 具有“优雅关闭”模式,在运行期间发送 SIGINT 或按下 Ctrl+C 可激活该模式。触发后,bisync 将尽最大努力在计时器到期前干净地退出。如果 bisync 正在传输文件,它将尝试通过完成已开始的操作但不接受更多任务来清空其队列。如果在 30 秒内无法完成,它将取消正在进行的传输,然后给自己最多 60 秒的时间来完成收尾工作、保存下次运行的状态并退出。使用 -vP 标志,你将看到持续的状态更新以及优雅关闭是否成功的最终确认。

在“优雅关闭”序列的任何时候,第二次发送 SIGINT 或按下 Ctrl+C 将触发立即的、非优雅的退出,这将使情况变得更混乱。如果使用 –recover 模式,通常仍可以进行可靠的恢复;否则,你需要执行 --resync

如果你计划使用优雅关闭模式,建议使用 –resilient–recover,并且不要使用 –inplace,否则你可能会在一侧留下部分写入的文件,这可能会在下一次运行时被误认为是真实文件。另请注意,在突然中断的情况下,会留下一个锁文件以阻止并发运行。在继续下一次运行之前,你需要删除它(或者如果使用 --max-lock,等待它自行过期)。

限制

支持的后端

Bisync 被视为测试版,已在以下后端进行了测试:

  • 本地文件系统
  • Google Drive
  • Dropbox
  • OneDrive
  • S3
  • SFTP
  • Yandex Disk
  • Crypt

目前尚未对其他服务进行全面测试。 如果它可以正常工作,或者部分正常工作,请告知我们,我们将更新列表。 按照以下说明运行测试套件以检查是否正常运行。

rclone bisync 的第一个版本要求两个底层后端都支持修改时间,否则拒绝运行。 从 v1.66 版本开始,此限制已被取消,因为 bisync 现在支持根据校验和和/或大小进行比较,而不是(或除了)修改时间。 有关详细信息,请参阅 --compare

并发修改

当使用 本地、FTP 或 SFTP 远程存储并搭配 --inplace 时,rclone 在复制时不会在目标位置创建临时文件。因此,如果连接丢失,创建的文件可能会损坏,这很可能会在下一次同步时传播回原始路径,导致数据丢失。因此,建议不要使用 --inplace

bisync 运行期间发生更改的文件可能会导致数据丢失。 在 rclone v1.66 之前,这种情况在高度动态的环境中很常见,即在同步过程中文件系统受到运行进程的频繁操作。 从 rclone v1.66 版本开始,bisync 重新设计为使用“快照”模型,大大降低了同步期间更改带来的风险。现在,在当前同步期间未检测到的更改将在后续同步中被检测到,并且不会再导致整个运行抛出严重错误。此外,还有一种机制可以标记文件,以便下次进行内部重新检查,以增加安全性。因此,现在不再需要仅在安静时段进行同步 —— 但是,请注意,如果文件恰好在被 bisync 读取/写入的那一刻发生更改,仍然可能会出现错误(与 rclone sync 中的情况相同)。 (另请参阅:--ignore-checksum--local-no-check-updated

空目录

默认情况下,一个路径上的新/已删除的空目录不会同步到另一侧。这是因为 bisync(和 rclone)原生处理文件,而不是目录。 但是,可以使用 --create-empty-src-dirs 标志更改此行为,该标志的工作方式与 synccopy 中的类似。使用该标志后,一侧创建或删除的空目录也将在另一侧创建或删除。 请注意以下几点:

  • --create-empty-src-dirs--remove-empty-dirs 不兼容。请只使用其中一个(或都不使用)。
  • 不建议在不运行 --resync 的情况下在 --create-empty-src-dirs 和默认设置(不使用 --create-empty-src-dirs)之间来回切换。这是因为这可能会让人觉得所有目录(不仅仅是空目录)都被创建/删除了,而实际上你只是在切换 bisync 对这些目录的可见性。虽然实际情况可能没有看起来那么严重,但最好还是坚持使用其中一种设置,并在需要切换时使用 --resync

重命名目录

默认情况下,在 Path1 一侧重命名文件夹会导致删除 Path2 一侧的所有文件,然后再将所有文件从 Path1 复制到 Path2。 Bisync 将此视为旧目录名中的所有文件都被删除,新目录名中的所有文件都是新的。

推荐的解决方案是使用 --track-renames,从 rclone v1.66 版本开始,bisync 现在支持该功能。 请注意,--track-renames--resync 期间不可用,因为 --resync 不会删除任何内容(--track-renames 仅支持 sync,不支持 copy)。

否则,重命名目录最有效和高效的方法是在两侧将其重命名为相同的名称。(从 rclone v1.64 版本开始,这样做之后不再需要 --resync,因为 bisync 会自动检测到 Path1 和 Path2 达成一致。)

默认使用 --fast-list

与大多数其他 rclone 命令不同,bisync 默认对支持的后端使用 --fast-list。在许多情况下,这是可取的,但是,在某些情况下,不使用 --fast-listbisync 可能会更快,并且存在一个已知问题,涉及拥有许多空目录的 Google Drive 用户。目前,避免使用 --fast-list 的推荐方法是在所有 bisync 命令中添加 --disable ListR。默认行为可能会在未来版本中更改。

大小写(和 Unicode)敏感性

v1.66 版本开始,大小写和 Unicode 形式的差异不再导致严重错误,并且(在文件系统之间进行比较时)的规范化处理遵循与 rclone sync 相同的标志和默认设置。 请参阅以下选项(bisync 均支持)以更精细地控制此行为:

请注意,在(可能很少见)使用 --fix-case 且文件在两侧都是新的/已更改的 且校验和匹配 且文件名大小写不匹配的情况下,出于 --fix-case 的目的,Path1 文件名被视为胜者(Path2 将被重命名以匹配它)。

Windows 支持

Bisync 已在 Windows 8.1、Windows 10 Pro 64 位和 Windows GitHub 运行器上进行了测试。

允许使用驱动器号,包括映射到网络驱动器的驱动器号(rclone bisync J:\localsync GDrive:)。 如果省略驱动器号,则默认使用 shell 当前驱动器。 驱动器号是一个字符后跟 :,因此云存储名称必须超过一个字符。

支持绝对路径(带或不带驱动器号)和相对路径(带或不带驱动器号)。

工作目录创建于 C:\Users\MyLogin\AppData\Local\rclone\bisync

请注意,bisync 输出可能会显示正斜杠 / 和反斜杠 \ 的混合使用。

在 Windows 上区分大小写不敏感的目录和文件名与 Linux 上区分大小写的情况时要小心。

过滤

有关如何编写和解释过滤规则,请参阅过滤文档

Bisync--filters-file 标志对 rclone 的 –filter-from 过滤机制进行了轻微扩展。 对于给定的 bisync 运行,你只能提供一个 --filters-file--include*--exclude*--filter 标志也受支持。

如何过滤目录

过滤目录树的部分内容是同步的关键功能。

你可能希望从同步中排除的目录树示例(始终位于 Path1/Path2 根级别之下):

  • 仅包含软件构建中间文件的目录树。
  • 包含应用程序临时文件和数据的目录树,例如 Windows 的 C:\Users\MyLogin\AppData\ 树。
  • 包含大文件、不太重要的文件或正在被正在运行的进程不断修改的文件的目录树。

另一方面,你可能只希望同步特定的目录,并排除其他所有目录。请参阅下面的示例:Windows 用户目录的包含式过滤器

过滤器文件编写指南

  1. 首先排除目录树:
    • 例如:- /AppData/
    • 末尾的 ** 不是必需的。一旦排除了给定的目录级别,rclone 将不会查看其下的任何内容。
    • 排除那些不需要的、大的、动态修改频繁的或可能存在访问权限问题的目录。
    • 首先排除这些目录将使 rclone 操作(大大)更快。
    • 也可以排除特定的文件,如下例中的 Dropbox 排除项。
  2. 决定哪种方式更简单(或更清晰):
    • 包含特定目录,因此排除其他所有内容 —— 或者 ——
    • 排除特定目录,因此包含其他所有内容
  3. 包含特定目录:
    • 添加类似这样的行:+ /Documents/PersonalFiles/** 以选择要包含在同步中的目录。
    • 末尾的 ** 指定包含指定目录树的完整深度。
    • 使用包含式过滤器时,Path1/Path2 根目录下的文件不包含在内。可以使用 + /* 包含这些文件。
    • 将 RCLONE_TEST 文件放在这些包含的目录树中。rclone 只会在这些目录树中查找这些文件。
    • 在过滤器文件的末尾添加 - ** 以排除其他所有内容。
    • 忽略步骤 4。
  4. 排除特定目录:
    • 像步骤 1 一样添加更多行。 例如:-/Desktop/tempfiles/- /testdir/。 同样,末尾的 ** 不是必需的。
    • 不要在文件中添加 - **。没有这一行,所有未明确排除的内容都将被包含在内。
    • 忽略步骤 3。

过滤文件语法的一些规则,是对过滤文档的扩展:

  • 行可以以空格和制表符开头 - rclone 会去除行首的空白字符。
  • 如果第一个非空白字符是 #,则该行是注释,将被忽略。
  • 空行将被忽略。
  • 过滤行的第一个非空白字符必须是 +-
  • +/- 和路径项之间只允许有一个空格。
  • 路径项中只使用正斜杠 (/),即使在 Windows 上也是如此。
  • 行的其余部分将被视为路径项。行尾的空白字符将被视为字面字符,可能是错误的。

示例:Windows 用户目录的包含式过滤器

这个 Windows 包含式示例基于同步根目录(Path1)设置为 C:\Users\MyLogin。策略是选择特定的目录与网络驱动器(Path2)进行同步。

  • - /AppData/ 排除了整个 Windows 存储数据的目录树,这些数据不需要同步。 在我的情况下,AppData 包含超过 11 GB 的我不关心的数据,并且 AppData 下的一些子目录我的用户登录无法访问,这会导致 bisync 严重中止。
  • Windows 在 C:\Users\MyLogin 处创建以大写和小写 NTUSER 开头的缓存文件。这些文件可能是动态的、被锁定的,通常是不关心的。
  • 只有少数包含我的数据的目录是我想要同步的,形式为 + /<path>。通过只选择我想要的目录树,避免了各种应用程序在 C:\Users\MyLogin\Documents 处创建的十几个以上的目录。
  • 通过添加 + /* 行,包含同步点根目录 C:\Users\MyLogin 中的文件。
  • 这是一个包含式过滤器文件,因此以 - ** 结尾,这将排除所有未明确包含的内容。
- /AppData/
- NTUSER*
- ntuser*
+ /Documents/Family/**
+ /Documents/Sketchup/**
+ /Documents/Microcapture_Photo/**
+ /Documents/Microcapture_Video/**
+ /Desktop/**
+ /Pictures/**
+ /*
- **

另外需要注意的是,Windows 实现了多个“库”链接,例如 C:\Users\MyLogin\My Documents\My Music 指向 C:\Users\MyLogin\Music。rclone 将这些视为链接,因此如果你想跟随这些链接,必须在 bisync 命令行中添加 --links。我发现尝试跟随这些链接时会出现权限错误,所以我不使用 rclone 的 --links 标志,但这样 rclone 会产生大量关于不跟随链接的 无法跟随符号链接… 噪音。可以通过在 bisync 命令行中添加 --quiet 来消除这些噪音。

用于 Dropbox 的排除式过滤文件示例

  • Dropbox 不允许同步列出的临时文件和配置/数据文件。- <文件名> 过滤器会排除同步树中任何位置出现的这些文件。考虑为你不需要同步的文件类型添加类似的排除项,例如核心转储文件和软件构建文件。
  • bisync 测试会在同步树的顶层创建 /testdir/,并且通常在测试后删除该树。如果在 /testdir/ 树存在时进行正常同步,--check-access 阶段可能会因 RCLONE_TEST 文件数量不平衡而失败。- /testdir/ 过滤器会阻止该树被同步。如果你不进行 bisync 开发测试,则不需要此排除项。
  • Path1/Path2 根目录下的其他所有内容都将被同步。
  • RCLONE_TEST 文件可以放置在树中的任何位置,包括根目录。

Dropbox 的过滤文件示例

# Filter file for use with bisync
# See https://rclone.cn/filtering/ for filtering rules
# NOTICE: If you make changes to this file you MUST do a --resync run.
#         Run with --dry-run to see what changes will be made.

# Dropbox won't sync some files so filter them away here.
# See https://help.dropbox.com/installs-integrations/sync-uploads/files-not-syncing
- .dropbox.attr
- ~*.tmp
- ~$*
- .~*
- desktop.ini
- .dropbox

# Used for bisync testing, so excluded from normal runs
- /testdir/

# Other example filters
#- /TiBU/
#- /Photos/

--check-access 如何处理过滤器

bisync 运行开始时,会使用用户指定的 --filters-file 为路径 1 和路径 2 收集文件列表。在检查访问权限阶段,bisync 会在这些列表中扫描 RCLONE_TEST 文件。 任何被 --filters-file 过滤掉的 RCLONE_TEST 文件都不会出现在列表中,因此在检查访问权限阶段不会被检查。

故障排除

阅读 bisync 日志

以下是两次正常运行的示例。第一次运行时,远程端有一个更新的文件。第二次运行时,本地和远程端之间没有差异。

2021/05/16 00:24:38 INFO  : Synching Path1 "/path/to/local/tree/" with Path2 "dropbox:/"
2021/05/16 00:24:38 INFO  : Path1 checking for diffs
2021/05/16 00:24:38 INFO  : - Path1    File is new                         - file.txt
2021/05/16 00:24:38 INFO  : Path1:    1 changes:    1 new,    0 newer,    0 older,    0 deleted
2021/05/16 00:24:38 INFO  : Path2 checking for diffs
2021/05/16 00:24:38 INFO  : Applying changes
2021/05/16 00:24:38 INFO  : - Path1    Queue copy to Path2                 - dropbox:/file.txt
2021/05/16 00:24:38 INFO  : - Path1    Do queued copies to                 - Path2
2021/05/16 00:24:38 INFO  : Updating listings
2021/05/16 00:24:38 INFO  : Validating listings for Path1 "/path/to/local/tree/" vs Path2 "dropbox:/"
2021/05/16 00:24:38 INFO  : Bisync successful

2021/05/16 00:36:52 INFO  : Synching Path1 "/path/to/local/tree/" with Path2 "dropbox:/"
2021/05/16 00:36:52 INFO  : Path1 checking for diffs
2021/05/16 00:36:52 INFO  : Path2 checking for diffs
2021/05/16 00:36:52 INFO  : No changes found
2021/05/16 00:36:52 INFO  : Updating listings
2021/05/16 00:36:52 INFO  : Validating listings for Path1 "/path/to/local/tree/" vs Path2 "dropbox:/"
2021/05/16 00:36:52 INFO  : Bisync successful

模拟运行的异常情况

--dry-run 消息可能会显示它试图删除某些文件。例如,如果某个文件在 Path2 上是新文件,而在 Path1 上不存在,那么通常它会被复制到 Path1。但启用 --dry-run 后,这些复制操作不会执行,这就导致了在 Path2 上尝试删除该文件的操作,不过又会被 --dry-run 阻止:... 由于是 --dry-run 模式,不执行删除操作

这种令人困惑的情况是 --dry-run 标志导致的结果。请仔细审查提议的删除操作,如果这些文件原本会被复制到 Path1,那么 Path2 上显示的删除威胁可以忽略。

重试机制

Rclone 内置了重试机制。如果使用 --verbose 运行,你会看到类似下面的错误和重试消息。这通常不是 bug。如果在运行结束时,你看到 Bisync successful 而不是 Bisync critical errorBisync aborted,那么运行就是成功的,你可以忽略这些错误消息。

以下运行示例展示了一个间歇性失败的情况。第 5 行和第 6 行是底层消息。第 6 行是一个向上冒泡的警告消息,传达了错误信息。Rclone 通常会对失败的命令进行重试,因此日志中可能会有大量此类消息。

由于第 7 行没有最终的错误/警告消息,说明 Rclone 在重试后从失败中恢复过来了,整个同步操作是成功的。

1: 2021/05/14 00:44:12 INFO  : Synching Path1 "/path/to/local/tree" with Path2 "dropbox:"
2: 2021/05/14 00:44:12 INFO  : Path1 checking for diffs
3: 2021/05/14 00:44:12 INFO  : Path2 checking for diffs
4: 2021/05/14 00:44:12 INFO  : Path2:  113 changes:   22 new,    0 newer,    0 older,   91 deleted
5: 2021/05/14 00:44:12 ERROR : /path/to/local/tree/objects/af: error listing: unexpected end of JSON input
6: 2021/05/14 00:44:12 NOTICE: WARNING  listing try 1 failed.                 - dropbox:
7: 2021/05/14 00:44:12 INFO  : Bisync successful

This log shows a Critical failure which requires a --resync to recover from. See the Runtime Error Handling section.

2021/05/12 00:49:40 INFO  : Google drive root '': Waiting for checks to finish
2021/05/12 00:49:40 INFO  : Google drive root '': Waiting for transfers to finish
2021/05/12 00:49:40 INFO  : Google drive root '': not deleting files as there were IO errors
2021/05/12 00:49:40 ERROR : Attempt 3/3 failed with 3 errors and: not deleting files as there were IO errors
2021/05/12 00:49:40 ERROR : Failed to sync: not deleting files as there were IO errors
2021/05/12 00:49:40 NOTICE: WARNING  rclone sync try 3 failed.           - /path/to/local/tree/
2021/05/12 00:49:40 ERROR : Bisync aborted. Must run --resync to recover.

拒绝下载“受感染”或“违规”文件

Google Drive 对某些文件类型(如 .exe.apk 等)设置了过滤,默认情况下,这些文件无法从 Google Drive 复制到本地文件系统。如果你遇到问题,请使用 --verbose 运行,以查看具体是哪些文件引发了问题。如果错误信息是 此文件已被识别为恶意软件或垃圾邮件,无法下载,可以考虑使用标志 –drive-acknowledge-abuse

Google Docs(以及其他未知大小的文件)

v1.66 版本开始,Google Docs(包括 Google Sheets、Slides 等)现在在 bisync 中得到支持,其选项、默认设置和限制与 rclone sync 相同。当在 Google Drive 和非 Google Drive 后端之间进行双向同步时,从 Google Drive 到非 Google Drive 的方向由 --drive-export-formats(默认值为 "docx,xlsx,pptx,svg")控制,从非 Google Drive 到 Google Drive 的方向由 --drive-import-formats(默认值为空)控制。

例如,使用默认的导出/导入格式,Google Drive 端的 Google Sheet 将同步为非 Google Drive 端的 .xlsx 文件。反之,文件名与现有 Google Sheet 匹配的 .xlsx 文件将同步到该 Google Sheet,而与现有 Google Sheet 不匹配的 .xlsx 文件将作为普通的 .xlsx 文件复制到 Google Drive(不会转换为 Google Sheet,尽管 Google Drive 网页浏览器界面可能仍会提供将其作为 Google Sheet 打开的选项)。

如果设置了 --drive-import-formats(默认情况下未设置),则所有指定格式的文件将转换为 Google Docs(前提是没有同名的现有 Google Doc)。注意:这种转换可能会造成大量数据丢失,在大多数情况下,这可能不是你想要的结果!

要像“Drive for Desktop”那样将 Google Docs 双向同步为 URL 快捷方式链接,请使用:--drive-export-formats url(或 其他选项)。

请注意,这些链接文件不能在非 Google Drive 端进行编辑 —— 如果你尝试将编辑后的链接文件同步回 Google Drive,将会出现错误。它们可以被删除(这将导致删除相应的 Google Doc)。如果你在非 Google Drive 端创建了一个与现有 Google Doc 不匹配的 .url 文件,双向同步它只会将字面意义上的 .url 文件复制到 Google Drive(不会创建 Google Doc)。因此,一般来说,将它们视为非 Google Drive 端的只读占位符,并在 Google Drive 端进行所有更改。

同样,即使使用其他导出格式,最好也只在 Google Drive 端移动/重命名 Google Docs。这是因为否则,bisync 会将此解释为一个文件被删除,另一个文件被创建,因此,它将删除 Google Doc 并在新路径创建一个新文件。(这个新文件是否为 Google Doc 取决于 --drive-import-formats。)

最后,请注意,Google Drive 端的所有 Google Docs 文件大小为 -1,且没有校验和。因此,不能使用 --checksum--size-only 标志可靠地同步它们。(确切地说:它们仍然会被创建/删除,bisync 的差异引擎会注意到更改并将其排队等待同步,但底层同步函数会认为它们相同并跳过它们。)为了解决这个问题,请使用默认的(修改时间和大小)选项,而不是 --checksum--size-only

要完全忽略 Google Docs,请使用 --drive-skip-gdocs

使用示例

Cron

Rclone 目前还没有内置的功能来监控本地文件系统的更改,因此必须定期盲目运行。 在 Windows 上,可以使用“任务计划程序”来实现,在 Linux 上,可以使用下面介绍的 Cron

第一个示例每 5 分钟在本地目录和 OwnCloud 服务器之间运行一次同步,并将输出记录到运行日志文件中:

# Minute (0-59)
#      Hour (0-23)
#           Day of Month (1-31)
#                Month (1-12 or Jan-Dec)
#                     Day of Week (0-6 or Sun-Sat)
#                         Command
  */5  *    *    *    *   /path/to/rclone bisync /local/files MyCloud: --check-access --filters-file /path/to/bysync-filters.txt --log-file /path/to//bisync.log

请参阅 crontab 语法 以了解 crontab 时间间隔表达式的详细信息。

如果你将 rclone bisync 作为 cron 作业运行,请将标准输出和标准错误重定向到一个文件。 第二个示例每小时执行一次与 Dropbox 的同步,并将所有标准输出(通过 >>) 和标准错误(通过 2>&1)记录到一个日志文件中。

0 * * * * /path/to/rclone bisync /path/to/local/dropbox Dropbox: --check-access --filters-file /home/user/filters.txt >> /path/to/logs/dropbox-run.log 2>&1

在主机之间共享加密文件夹树

bisync 可以使本地文件夹与云服务保持同步,但如果你有一些高度敏感的文件需要同步,该怎么办呢?

使用云服务可以在家庭网络、外出时使用的个人笔记本电脑以及工作电脑之间交换日常和敏感的个人文件。日常数据并不敏感。对于敏感数据,可以配置一个 rclone 加密远程存储,使其指向本地磁盘树中与 Dropbox 进行双向同步的子目录,然后为这个本地加密目录与主同步树之外的一个目录设置双向同步。

Linux 服务器设置

  • /path/to/DBoxroot 是我本地同步树的根目录。其中有许多子目录。
  • /path/to/DBoxroot/crypt 是加密文件的根子目录。这个本地目录目标被设置为一个名为 Dropcrypt: 的 rclone 加密远程存储。请参阅下面的 rclone.conf 片段。
  • /path/to/my/unencrypted/files 是我敏感文件的根目录,这些文件未加密,也不在与 Dropbox 同步的树中。
  • 为了将我本地的未加密文件与加密的 Dropbox 版本进行同步,我手动运行 bisync /path/to/my/unencrypted/files DropCrypt:。这一步可以打包成一个脚本,在最后一步的完整 Dropbox 树同步前后运行,从而使敏感文件保持同步。
  • bisync /path/to/DBoxroot Dropbox: 通过 cron 定期运行,使我的整个本地同步树与 Dropbox 保持同步。

Windows 笔记本电脑设置

  • Dropbox 客户端会使本地树 C:\Users\MyLogin\Dropbox 始终与 Dropbox 保持同步。我也可以使用 rclone bisync 来实现这一点。
  • C:\Users\MyLogin\Documents\DropLocal 是一个单独的目录树,用于存放未加密的文件和文件夹。
  • 为了将我本地的未加密文件与加密的 Dropbox 版本进行同步,我手动运行以下命令:rclone bisync C:\Users\MyLogin\Documents\DropLocal Dropcrypt:
  • 然后 Dropbox 客户端会将更改同步到 Dropbox。

rclone.conf 片段

[Dropbox]
type = dropbox
...

[Dropcrypt]
type = crypt
remote = /path/to/DBoxroot/crypt          # on the Linux server
remote = C:\Users\MyLogin\Dropbox\crypt   # on the Windows notebook
filename_encryption = standard
directory_name_encryption = true
password = ...
...

测试

只有当你在为 rclone 进行开发工作时,才需要阅读此部分内容。你需要在本地拥有 rclone 源代码才能进行 bisync 测试。

Bisync 有一个专门的测试框架,它实现在 rclone 源代码树中的 bisync_test.go 文件里。测试套件基于 go test 命令。一系列的测试用例存储在 cmd/bisync/testdata 目录下的子目录中。可以通过目录名来调用单个测试用例,例如: go test . -case basic -remote local -remote2 gdrive: -v

测试会在远程创建一个临时文件夹,并在测试结束后清除它。 如果在测试运行期间出现间歇性错误,并且 rclone 进行了重试,这些错误会被捕获并标记为无效的不匹配(MISCOMPARE)。重新运行测试应该可以通过。可以将此类失败视为干扰因素。

测试命令语法

usage: go test ./cmd/bisync [options...]

Options:
  -case NAME        Name(s) of the test case(s) to run. Multiple names should
                    be separated by commas. You can remove the `test_` prefix
                    and replace `_` by `-` in test name for convenience.
                    If not `all`, the name(s) should map to a directory under
                    `./cmd/bisync/testdata`.
                    Use `all` to run all tests (default: all)
  -remote PATH1     `local` or name of cloud service with `:` (default: local)
  -remote2 PATH2    `local` or name of cloud service with `:` (default: local)
  -no-compare       Disable comparing test results with the golden directory
                    (default: compare)
  -no-cleanup       Disable cleanup of Path1 and Path2 testdirs.
                    Useful for troubleshooting. (default: cleanup)
  -golden           Store results in the golden directory (default: false)
                    This flag can be used with multiple tests.
  -debug            Print debug messages
  -stop-at NUM      Stop test after given step number. (default: run to the end)
                    Implies `-no-compare` and `-no-cleanup`, if the test really
                    ends prematurely. Only meaningful for a single test case.
  -refresh-times    Force refreshing the target modtime, useful for Dropbox
                    (default: false)
  -verbose          Run tests verbosely

注意:与必须以双破折号 (--) 开头的 rclone 标志不同,测试命令标志可以使用单破折号 (-) 或双破折号 (--) 开头。

运行测试

  • go test . -case basic -remote local -remote2 local 使用本地文件系统运行 test_basic 测试用例,将一个本地目录与另一个本地目录进行同步。 测试脚本的输出会显示在控制台,而 scenario.txt 中的命令输出会被发送到 .../workdir/test.log 文件中,最后会将该文件与参考副本进行比较。
  • go test 之后的第一个参数应该是包含 bisync 源代码的目录的相对名称。如果直接在该目录下运行测试,该参数将为 .(当前目录),如下述大多数示例所示。 如果从 rclone 源代码目录运行 bisync 测试,命令应该是 go test ./cmd/bisync ...
  • 测试引擎会对 rclone 的输出进行处理,以确保其与参考列表和日志具有可比性。
  • 测试场景位于 ./cmd/bisync/testdata 目录下。-case 测试参数应与该目录下的子目录的完整名称相匹配。磁盘上的每个测试子目录名称必须以 test_ 开头,为简洁起见,在命令行中可以省略该前缀。此外,为方便起见,名称中的下划线可以用破折号代替。
  • go test . -remote local -remote2 local -case all 运行所有测试。
  • Path1Path2 可以是关键字 local,也可以是已配置的云服务名称。 go test . -remote gdrive: -remote2 dropbox: -case basic 将在这两个服务之间运行测试,而不会将任何文件传输到本地文件系统。
  • 测试运行的标准输出和标准错误控制台输出可以定向到一个文件,例如: go test . -remote gdrive: -remote2 local -case all > runlog.txt 2>&1

测试执行流程

  1. 将测试用例 initial 目录中的基础设置应用到 Path1Path2 文件系统(通过 rclone 将 initial 目录复制到 Path1,然后使用 rclone 将 Path1 同步到 Path2)。
  2. 应用 scenario.txt 文件中的命令,输出将定向到测试工作目录中的 test.log 文件。 通常,scenario.txt 文件中的第一个实际命令是执行 --resync,这将在测试工作目录(相对于临时测试目录的 .../workdir/)中建立基准 {...}.path1.lst{...}.path2.lst 文件。 在测试过程中会执行各种命令并进行列表快照。
  3. 最后,将测试工作目录的内容与测试用例的参考目录的内容进行比较。

测试注意事项

  • 测试用例位于 ./cmd/bisync/testdata 目录下的各个子目录中。 命令行中对测试的引用应理解为引用 testdata 目录下的一个子目录。例如, go test ./cmd/bisync -case dry-run -remote gdrive: -remote2 local 引用的是 ./cmd/bisync/testdata/test_dry_run 目录下的测试用例。
  • 测试工作目录位于相对于临时测试目录的 .../workdir 中,在 Linux 系统上通常位于 /tmp 目录下。
  • 本地测试同步树会在系统临时目录下创建一个名为 bisync.XXX 的临时目录。
  • 远程测试同步树位于 <remote:>/bisync.XXX/ 目录下的一个临时目录中。
  • 在相应的本地或云测试远程的临时目录中会创建 path1 和/或 path2 子目录。
  • 默认情况下,每次测试运行后会删除 Path1Path2 测试目录以及工作目录。使用 -no-cleanup 标志可以在验证和调试特定测试时禁用对这些目录的清理。 在运行另一个测试之前,这些目录会被清空,与 -no-cleanup 标志的使用无关。
  • 你可能需要在正常的 bisync --filters-file 中添加 - /testdir/,这样正常的同步操作就不会尝试同步测试临时目录,因为在某些测试用例中,这些目录可能存在 RCLONE_TEST 不匹配的情况,否则会触发 --check-access 系统。 --check-access 机制会硬编码忽略 bisync/testdata 目录下的 RCLONE_TEST 文件,因此即使测试树中存在检查文件不匹配的情况,测试用例也可以位于同步树中。
  • 某些 Dropbox 测试可能会失败,特别是会输出以下消息: src 和 dst 相同,但不删除并重新上传就无法设置修改时间 这是预期的,是由于 Dropbox 处理修改时间的方式导致的。 你应该使用 -refresh-times 测试标志来解决这个问题。
  • 如果 Dropbox 测试达到了请求限制并输出错误消息 too_many_requests/...: 请求或写入操作过多。 请遵循 Dropbox 应用 ID 说明

更新参考结果

有时,即使 bisync 源代码有微小的更改,也可能会导致许多日志文件出现细微的变化。手动更新这些文件将是一场噩梦。

-golden 标志会将每个测试用例的 test.log*.lst 列表存储到各自的参考目录中。参考结果会自动包含通用字符串,而不是本地或云路径,这意味着在使用不同的云服务运行时,它们应该是匹配的。

你正常的工作流程可能如下:

  1. 在本地克隆 rclone 源代码。
  2. 修改 bisync 源代码并检查是否可以构建。
  3. 运行整个测试套件 go test ./cmd/bisync -remote local
  4. 如果某些测试显示日志有差异,单独重新检查这些测试,例如: go test ./cmd/bisync -remote local -case basic
  5. 如果你确认了差异,可以一次性将所有测试的结果保存为参考结果: go test ./cmd/bisync -remote local -golden
  6. 使用逐字差异比较:git diff --word-diff ./cmd/bisync/testdata/。 请注意,通常情况下,普通的行级差异比较在这里没有太大用处。
  7. 仔细检查差异!
  8. 只有在确定无误的情况下才提交更改 (git commit)。 如果不确定,可以保存代码更改,然后从 git 中清除日志差异: git reset [--hard]

测试场景结构

  • <testname>/initial/ 包含一个文件树,该文件树将作为 Path1Path2 测试目录的初始条件。
  • <testname>/modfiles/ 包含用于修改 Path1 和/或 Path2 文件系统的文件。
  • <testname>/golden/ 包含测试用例完成时测试工作目录 (workdir) 的预期内容。
  • <testname>/scenario.txt 包含测试的主体内容,以各种修改文件、运行 bisync 和进行列表快照的命令形式存在。 这些命令的输出会被捕获到 .../workdir/test.log 文件中,以便与参考文件进行比较。

支持的测试命令

  • test <一些消息> 将该行输出到控制台和 test.log 文件中: test 同步在选项 x、y、z 下正常工作
  • copy-listings <前缀> 使用指定的前缀保存测试工作目录中所有 .lst 列表的副本: save-listings exclude-pass-run
  • move-listings <前缀>copy-listings 类似,但会删除源文件。
  • purge-children <目录> 这将删除给定目录下的所有子文件并清空所有子目录,但保留父目录不变。对于使用 Google Drive 的测试,这种行为很重要,因为删除并重新创建父目录会更改其 ID。
  • delete-file <文件> 删除单个文件。
  • delete-glob <目录> <模式> 删除给定目录下一级深度、名称与给定通配符模式匹配的一组文件。
  • touch-glob YYYY-MM-DD <目录> <模式> 更改一组文件的修改时间。
  • touch-copy YYYY-MM-DD <源文件> <目标目录> 更改文件的修改时间,然后将其复制到目标目录。
  • copy-file <源文件> <目标目录> 将单个文件复制到给定目录。
  • copy-as <源文件> <目标文件> 与上述命令类似,但目标必须同时包含目录和目标文件的新名称。
  • copy-dir <源目录> <目标目录>sync-dir <源目录> <目标目录> 复制/同步一个目录。相当于 rclone copyrclone sync
  • list-dirs <目录> 相当于 rclone lsf -R --dirs-only <目录>
  • bisync [选项] 针对 -remote-remote2 运行 bisync。

支持的替换术语

  • {testdir/} - 测试用例的根目录
  • {datadir/} - 测试用例根目录下的 modfiles 目录
  • {workdir/} - 临时测试工作目录
  • {path1/} - Path1 测试目录树的根目录
  • {path2/} - Path2 测试目录树的根目录
  • {session} - 测试列表的基本名称
  • {/} - 操作系统特定的路径分隔符
  • {spc}{tab}{eol} - 空白字符
  • {chr:HH} - 具有给定十六进制代码的原始字节

{dir/} 这样命名的替换术语的结果将以 /(在 Windows 上为反斜杠)结尾,因此在使用时无需包含斜杠,例如 delete-file {path1/}file1.txt

基准测试

本节内容正在完善中。

以下是一些关于规模、执行时间和内存使用的数据点。

第一组数据是在本地磁盘和 Dropbox 之间进行测试得到的。 speedtest.net 的下载速度约为 170 Mbps,上传速度约为 10 Mbps。已经同步了 500 个文件(每个文件约 9.5 MB)。在一个新目录中添加了 50 个文件,每个文件约 9.5 MB,总计约 475 MB。

更改情况 操作和时间 总体运行时间
500 个文件已同步(无需移动) Path1Path2 进行 1 次列表操作 1.5 秒
500 个文件已同步并使用 --check-access Path1Path2 进行 1 次列表操作 1.5 秒
远程端有 50 个新文件 排队进行 50 次下载复制操作:27 秒 29 秒
移动本地目录 排队进行 50 次上传复制操作:410 秒,50 次上传删除操作:9 秒 421 秒
移动远程目录 排队进行 50 次下载复制操作:31 秒,50 次下载删除操作:<1 秒 33 秒
删除本地目录 排队进行 50 次上传删除操作:9 秒 13 秒

接下来的数据来自一位用户的应用程序。他们在 Windows 本地磁盘和某个远程云之间同步了约 400GB 的数据,包含 196 万个文件。文件完整路径的平均长度为 35 个字符(这会影响加载时间和所需的 RAM)。

  • 将之前的列表加载到内存中(196 万个文件,列表文件大小为 140 MB)大约需要 30 秒,占用约 1GB 的 RAM。
  • 获取本地文件系统的新列表(生成 140 MB 的输出文件)大约需要 XXX 秒。
  • 获取远程文件系统的新列表(生成 140 MB 的输出文件)大约需要 XXX 秒。网络下载速度测量为 XXX Mb/s。
  • 一旦加载了之前和当前的 Path1Path2 列表(总共需要加载四个列表,每次加载两个),确定差异的速度非常快(对于这个测试用例,只需几秒钟),任何需要复制的文件的传输时间主要取决于网络带宽。

参考资料

rclone 的 bisync 实现源自 rclonesync-V2 项目,包括文档和测试机制, 并得到了 @cjnaz 的全力支持和鼓励。

rclone bisync 在本质上与一系列其他项目类似:

Bisync 采用了差异同步技术,该技术基于记录两个同步端所执行的更改历史。 请参阅 Neil Fraser 的文章 中的“双影子方法”部分。

另外,请注意 Benjamin Pierce 发表的许多关于 Unison 和同步的学术论文。

变更日志

v1.69.1

  • 修复了在某些条件下列表无法捕获并发修改的问题

v1.68

  • 修复了影响将修改时间舍入到较低精度的后端的问题。

v1.67

  • 增加了针对所有后端的集成测试。

v1.66

  • 现在复制和删除操作在一个操作中处理,而不是两个操作
  • 现在支持 --track-renames--backup-dir
  • 解决了 local/ftp/sftp 上部分上传的已知问题(除非使用 --inplace
  • 现在从同步结果生成最终列表,避免了重新列表的需要
  • Bisync 现在对 bisync 运行期间发生的更改更具弹性,并且更不容易出现严重错误/未检测到的更改
  • Bisync 现在能够在不确定的情况下回滚文件列表,本质上是将文件标记为下次需要重新检查。
  • 现在支持一些基本的终端颜色,可以使用 --color (AUTO|NEVER|ALWAYS) 进行控制
  • Path1Path2 的初始列表快照现在使用与 checksync 相同的“行进”基础设施并发生成,以提高性能并减少 错误风险
  • 修复了 Unicode 规范化和不区分大小写的处理,支持 --fix-case--ignore-case-sync--no-unicode-normalization
  • --resync 现在效率更高(特别是对于使用 --create-empty-src-dirs 的用户)
  • 现在支持 Google Docs(以及其他未知大小的文件)(与 sync 中的选项相同)
  • 同步冲突重命名前的相等性检查现在在 check 不可用时会回退到 cryptcheck(如果可能)或 --download,而不是 --size-only
  • 当配置被特定后端标志覆盖时,Bisync 现在不会找不到正确的列表文件
  • Bisync 现在完全支持基于大小、修改时间和校验和的任意组合进行比较,解除了之前对不支持修改时间的后端的限制
  • Bisync 现在支持“优雅关闭”模式,可在不使用 --resync 的情况下提前干净地取消运行
  • 新的 --recover 标志允许在中断时进行可靠恢复,无需使用 --resync
  • 新的 --max-lock 设置允许锁文件自动更新和过期,以便在运行中断时更好地自动恢复
  • Bisync 现在支持通过新的 --conflict-resolve--conflict-loser--conflict-suffix 标志自动解决同步冲突并自定义重命名行为
  • 新的 --resync-mode 标志允许在 --resync 期间更好地控制保留哪个版本的文件
  • 当设置了 --resilient 时,Bisync 现在支持 --retries--retries-sleep

v1.64