我为本地网络做一些经常使用的存储库的夜间和每周镜像。有几次,有人试图在 rsync 发生时进行更新,但由于预期的文件还没有全部到位而失败。
是否可以进行 rsync 以使所有更改的文件在完成时仅以正确的名称出现?我知道 rsync 在每次传输过程中使用临时 .hidden 文件,但是我可以推迟重命名直到它以某种方式完成吗?
或者,我似乎可以使用 --backup 选项将所有更改移动到一个目录并在之后自动移动它们,但我希望该功能与现在的功能相反。
我在 Linux 上是为了它的价值。
我为本地网络做一些经常使用的存储库的夜间和每周镜像。有几次,有人试图在 rsync 发生时进行更新,但由于预期的文件还没有全部到位而失败。
是否可以进行 rsync 以使所有更改的文件在完成时仅以正确的名称出现?我知道 rsync 在每次传输过程中使用临时 .hidden 文件,但是我可以推迟重命名直到它以某种方式完成吗?
或者,我似乎可以使用 --backup 选项将所有更改移动到一个目录并在之后自动移动它们,但我希望该功能与现在的功能相反。
我在 Linux 上是为了它的价值。
您可以使用该
--link-dest=
选项。基本上你会创建一个新文件夹,所有文件都硬链接到新文件夹。一切完成后,您只需交换文件夹名称并删除旧文件夹名称即可。在 Linux 中不可能做到 100% 原子,因为它没有内核/VFS 支持。但是,交换名称实际上只需要 2 个系统调用,因此完成它应该花费不到 1 秒的时间。只能在 Darwin (MAC/OSX) 上使用 HFS 文件系统上的 exchangedata 系统调用。
我对备份 [到磁盘] 做了类似的事情,
rsync
由于备份运行时守护程序更新文件,我遇到了同样的问题。与许多程序不同,rsync 有许多不同的错误代码 [参见手册页底部]。感兴趣的是两个:
当 rsync 进行传输并遇到其中一种情况时,它不会立即停止。它跳过并继续它可以传输的文件。最后,它显示了返回码。
因此,如果您收到错误 23/24,只需重新运行 rsync。随后的运行速度会更快,通常只是传输上一次运行中丢失的文件。最终,你会[或应该得到]一个干净利落的运行。
至于原子性,我在传输过程中使用“tmp”目录。然后,当 rsync 运行干净时,我将其 [原子地] 重命名为
<date>
我也使用该
--link-dest
选项,但我使用它来保留增量备份(例如--link-dest=yesterday
每天)虽然我自己没有使用过它,但它
--partial-dir=DIR
可以防止隐藏文件弄乱备份目录。确保 DIR 与备份目录位于同一文件系统上,因此重命名将是原子的当我在 perl 中执行此操作时,我编写了一个脚本,该脚本总结了我一直在说的内容,并针对您的特定情况提供了更详细/更精确的内容。它采用类似 tcsh 的语法,[未经测试且有点粗糙],但将其视为伪代码,以根据您的选择编写自己的
bash
,perl
,脚本。python
请注意,它对重试没有限制,但您可以根据自己的意愿轻松添加。不确定这是否会对您有所帮助,但是...
如果您不介意每次都复制整个数据集并且可以使用符号链接来引用目标目录,那么您应该能够将所有内容同步到一个临时目录中,然后交换(rename())新旧以原子方式进行符号链接,如下所示:
运行
rename("new", "current")
= 0并给出
即使要使其正常工作,任何尝试从此设置中读取的客户端都应该
cd
在尝试任何读取之前进入符号链接引用的目录,否则他们可能会从旧副本和新副本中加载代码/数据的某些部分。镜像同步是自动的(cron任务或类似任务)吗?如果是这样,您可能为此使用了专门的操作系统用户,对吗?所以解决方案可能是,而不是简单地复制:
缺点是在同步过程中(不确定需要多长时间)目标目录将无法访问。你需要自己决定这里是否可以。