我想在两个系统之间同步目录。为了使其更有趣,同步只能在一个方向上完成,即:
- 如果在源目录中删除文件,则如果先前已传输该文件,则也必须在目标目录中删除该文件
- 目标目录中已删除的文件不得在源目录中删除
- 部分传输的文件(例如由于网络问题)必须在下次同步时完成
- 源目录中的新文件必须传输到目标目录
- 目标目录中已删除的文件不得重新传输
这意味着源系统基本上具有主控角色,但目标系统中已删除的文件不会被强制恢复。
两个 Linux 系统都有 rsync/ssh/scp 可用。
源目录中的新文件以这样一种方式创建,可以使用它们的 mtime 来检测它们,例如:
if mtime(file) > date-of-last-sync then: it is a new file that needs to be transfered
此外,源目录中的现有文件不会更改,即同步不需要检查已(完全)传输的文件中的差异。
答案1
如果您不打算使用远程文件系统作为已传输内容的数据源,那么您需要从外部跟踪之前已成功传输的文件,然后将它们从将来的传输中排除。
rsync
可以基于以下内容包含和排除文件图案位于文件中,以便您可以在传输中包含特定的文件列表。然后将该列表从未来的传输中排除。
#!/usr/bin/env bash
set -e
track_dir=~/.track_xfer
inc_file="$track_dir/include_files"
exc_file="$track_dir/exclude_files"
xfer_dir=~/testrsync
xfer_dest=~/testrsync_dest
mkdir -p "$track_dir"
touch $exc_file
cd "$xfer_dir"
# find files and create rsync filter list
find . -type f -print0 | perl -e '
$/="\0";
while (<>){
chomp;
$_ =~ s!^\.!!; # remove leading .
$f = quotemeta; # quote special chars
$f =~ s!\\/!/!g; # fix quoted paths `/`
print $f."\n";
}' > "$inc_file"
# Run the rsync
rsync -va --delete --exclude-from "$exc_file" --include-from "$inc_file" "$xfer_dir/" "$xfer_dest"
# Add the included/transferred files to the exclusion list
cat "$inc_file" "$exc_file" > "$exc_file".tmp
sort "$exc_file".tmp | uniq > "$exc_file"
您可能需要一些更rsync
具体的正则表达式引用,但 Perlquotemeta
功能和替换是我想到的第一个简单的解决方案。
主要问题是处理文件名中的任何特殊字符。如果您想处理名称中的新行或制表符以及其他奇怪的事情,那么您将不得不perl
在解析和生成包含模式列表的(或其他)中投入更多的工作。如果您可以将传输文件的名称限制为简单的字符集,那么您就不必太担心此步骤。这perl
是一个折中的解决方案,应该可以帮助您克服最常见的正则表达式字符。
rsync
使用包含列表而不是让其自行拉出整个目录的原因是这样您就可以为后续排除列表提供一个已定义/完整的文件列表。您可能可以通过解析传输的文件的rsync
输出或 a--log-file=FILE
来获得相同的结果,但这看起来有点困难。
答案2
Rsync 将完全按照您的要求进行操作rsync -a --delete
(-x
如果您需要 xattrs,例如对于 selinux,请添加)。
Rsync永远不会删除源中的文件,但--delete
会删除目标中源中不存在的所有文件。
它将通过增量更新机制更新部分传输的文件。 AFAIR rsync 将首先检查 mtime(+文件大小),并且仅当存在不匹配时才会完成指纹识别和增量更新。
答案3
请阅读手册页,因为它应该可以回答您的所有问题。该命令man rsync
应显示手册页。
rsync 将验证文件是否未更改。它在这方面非常高效,并且从未显着减慢我的传输的 rsync 时间。您可以通过在上次运行后立即计时 rsync 运行来估计所需的时间。
rsync 是一种单向同步,不会改变源。您可以安全地使用只能读取源文件但没有写入权限的用户标识。然而,这不是必要的。
当您重新运行 rsync 时,它将恢复任何部分完成的传输。
如果您使用删除选项之一,rsync 只会删除目标上的文件。
编辑:为了防止重新传输从目标目录中删除的文件,您需要为这些文件创建一个排除列表。即使它们已更新,这也会将它们排除在传输之外。或者,您可以截断文件而不是删除它们并使用该--update
标志。截断后更新的文件将被复制。
您可能会发现使用增量 tar 备份可以更好地满足您的需求。可以通过 ssh 连接将一个 tar 的输出通过管道传输到另一个 tar。这将拾取自上次备份以来创建或修改的所有文件,但不会传输任何其他文件。