春江暮客

春江暮客的个人学习分享网站

rsync 实战:先预览文件变化,再通过 SSH 同步目录

2026-09-18 技术
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.txtnotes/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 给它起一个方便复用的名称。

友情链接

其它