rsync 实战:先预览文件变化,再通过 SSH 同步目录
目录里只改了两个文件,想把更新传到服务器。执行复制命令之前,最好先回答两个问题:文件最终会落在哪个路径?目标目录中的哪些内容会发生变化?
本文先用本地临时目录做练习,观察每一步的结果。确认行为后,再复用上一篇 SSH 配置教程 中的服务器名称进行远程传输。
1. 准备一组练习文件
先检查本机安装的实现:
rsync --version
下文的本地练习已用 macOS 上的 openrsync 验证,该实现报告兼容 rsync 2.6.9。不同实现的输出格式可能略有差别。如果没有这个命令,先通过系统的包管理器安装 rsync。
在同一个终端里执行下面的命令,后续步骤也继续使用这个终端:
demo_dir=$(mktemp -d)
mkdir -p "$demo_dir/source/notes" "$demo_dir/destination"
printf 'hello rsync\n' > "$demo_dir/source/hello.txt"
printf 'write a post\n' > "$demo_dir/source/notes/todo.txt"
printf 'demo metadata\n' > "$demo_dir/source/.DS_Store"
printf 'Working directory: %s\n' "$demo_dir"
源目录现在包含两个文本文件,以及一个用于演示排除规则的 .DS_Store 文件。现有项目不会被修改。
2. 先看传输计划
rsync -rtin --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
这里的 -r 表示递归处理目录,-t 保留修改时间,-i 列出逐项变化,-n 表示只预演。排除规则会跳过演示用的元数据文件。基本参数说明见 openrsync 手册。
预览应列出 hello.txt、notes/ 和 notes/todo.txt。此时检查目标目录:
ls -A "$demo_dir/destination"
应该没有输出,因为文件还没有传过去。确认后,只去掉参数组合中的 n:
rsync -rti --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
cat "$demo_dir/destination/hello.txt"
cat "$demo_dir/destination/notes/todo.txt"
两段文字应与源文件一致。本例针对普通文件和目录,不是一套完整保留权限、所有者、符号链接及其他文件系统元数据的备份方案。
3. 看清源目录末尾的斜杠
第一次传输后,目录结构是:
destination/
├── hello.txt
└── notes/
└── todo.txt
再创建一个独立目标,把源目录末尾的 / 去掉进行对比:
mkdir -p "$demo_dir/nested"
rsync -rti --exclude='.DS_Store' \
"$demo_dir/source" "$demo_dir/nested/"
cat "$demo_dir/nested/source/hello.txt"
这次 nested 里面多了一层 source 目录。实际使用时,可以先写下一个文件应该到达的完整路径,再核对预览结果,避免同步成功却放错了位置。
4. 重复同步,再修改一个文件
重新运行最初的预览:
rsync -rtin --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
对于这组没有变化的练习文件,逐项输出应为空。接着追加一行文字,再预览:
printf 'second version\n' >> "$demo_dir/source/hello.txt"
rsync -rtin --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
现在应看到 hello.txt 出现在变化列表里。运行对应的不带 n 的命令,就可以传输这次更新。
rsync 默认根据文件大小和修改时间判断是否需要更新文件内容,因此预览为空并不等于逐字节校验通过。具体机制见 rsync 手册中的 quick check 说明。
5. 复用 SSH 主机配置
远程示例中的 blogbox 必须已经是 ~/.ssh/config 里可正常连接的 Host 名称。用户名、地址和自定义端口都可以放在该配置块中,详见 OpenSSH 配置说明。
先检查远程命令,并准备专用练习目录:
ssh blogbox 'rsync --version'
ssh blogbox 'mkdir -p "$HOME/rsync-demo"'
这种 SSH 传输需要两台机器都安装 rsync。命令中的 -e ssh 显式指定 SSH 作为传输通道,详见 rsync 安装与连接说明。
先预览上传,检查输出后再实际执行:
rsync -rtin -e ssh --exclude='.DS_Store' \
"$demo_dir/source/" blogbox:rsync-demo/
rsync -rti -e ssh --exclude='.DS_Store' \
"$demo_dir/source/" blogbox:rsync-demo/
ssh blogbox 'cat "$HOME/rsync-demo/hello.txt"'
在常规 SSH 配置下,这个相对远程路径指向登录账户主目录中的 rsync-demo。检查结果应包含 hello.txt 的两行文字。先在练习目录里完成验证,再替换成生产环境路径。远程预览仍然会连接服务器,也不能保证之后的实际写入一定成功。
6. 观察目标目录独有的文件
回到本地练习,手动在目标目录增加一个文件:
printf 'keep me\n' > "$demo_dir/destination/destination-only.txt"
rsync -rti --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
cat "$demo_dir/destination/destination-only.txt"
这个文件仍然存在。想查看删除计划而不执行删除,可以运行:
rsync -rtin --delete --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
预览应把 destination-only.txt 列为待删除项。练习时保留 n,去掉它就会实际应用删除。参数的作用范围见 rsync 手册。
即使没有 --delete,同步也可能用源文件版本覆盖目标中的已有文件。目标里有无法重新生成的工作成果时,应保留可恢复的副本。
实际传输失败时怎么检查
远程提示找不到 rsync,就到对应机器安装;无法解析 blogbox 或认证失败,回到 SSH 排查步骤;目标目录无法写入,则检查远程账户和目录权限。
每换一个新目标,都重复一次“预览、核对路径、执行、检查结果文件”。命令稳定后,还可以用 just 给它起一个方便复用的名称。
- 原文作者:春江暮客
- 原文链接:https://www.bobobk.com/rsync-preview-sync-workflow.html
- 版权声明:本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。