TT Lab
开始
学习 学习路径 课程

SSH 与文件传输

用 rsync 做同步

在 TT Lab 中继续学习

目标

亲手确认 rsync 的核心选项。尤其是末尾斜杠规则、--delete 的风险与保护措施、--link-dest 多代备份,这三项要亲自制作。

为什么重要

rsync 是用得最多、也最容易用错的工具。-a 不包含 ACL、扩展属性和硬链接;源路径末尾的一个斜杠会改变目录深度;源目录为空时 --delete 会把目标清空——这三点都曾造成过真实的事故。相反,--link-dest 是 rsync 最优美的功能。每一代看起来都像完整快照,而磁盘只为变更的部分占用空间。

步骤

  1. 在 /root/sync/src 之下创建以下内容:app/main.py、app/util.py、conf/app.yaml、logs/app.log、logs/error.log。每个文件中随便写入至少一行内容。
  2. 对把 /root/sync/src/ 同步到 /root/sync/dst1/ 的操作执行 dry-run,同时显示变更明细,并把结果保存到 /root/sync/dryrun.txt。
  3. 通过 SSH 真正执行同样的同步。目标是 root@127.0.0.1:/root/sync/dst1/,端口为 2222,密钥为 /root/.ssh/id_labhub。完成后 /root/sync/dst1/app/main.py 必须存在。
  4. 验证末尾斜杠的差异。把 /root/sync/src(没有斜杠)发送到 /root/sync/dst2/ 时,必须生成 /root/sync/dst2/src/app/main.py。
  5. 编写 /root/sync/backup.sh 脚本。它要以 set -euo pipefail 开头,包含在源目录为空时以退出码 1 中止的检查,并使用 --delete 把 /root/sync/src/ 同步到 /root/sync/dst3/。源路径要以第一个参数接收,没有参数时使用 /root/sync/src/——评分器会把空目录作为第一个参数传入,确认保护措施真的起作用。运行脚本,创建 /root/sync/dst3。
  6. 排除 logs/ 之下的内容,把 /root/sync/src/ 同步到 /root/sync/dst4/。/root/sync/dst4/logs 不得存在。
  7. 创建多代备份。先完整同步到 /root/sync/gen/daily.1/,再用 --link-dest 创建 /root/sync/gen/daily.0/。未变更的文件在两代之间必须共享同一个 inode。
  8. 把 /root/sync/final.txt 写成下面这 3 行。 PENDING=<3번과 같은 동기화를 다시 dry-run 했을 때 전송 예정 파일 수> / DST4_HAS_LOGS=no / SHARED_INODE=yes(第一项的占位符为再次对与第 3 步相同的同步执行 dry-run 时预定传输的文件数) PENDING 必须为 0。

参考

创建源目录树

在 /root/sync/src 之下创建以下内容:app/main.py、app/util.py、conf/app.yaml、logs/app.log、logs/error.log。每个文件中随便写入至少一行内容。

把子目录和日志文件混在一起,后面步骤中的排除规则才有意义。

先做模拟

对把 /root/sync/src/ 同步到 /root/sync/dst1/ 的操作执行 dry-run,同时显示变更明细,并把结果保存到 /root/sync/dryrun.txt。

请同时使用两个选项:一个只显示将会改变什么而不做实际变更,另一个逐行显示变更内容。

通过 SSH 实际同步

通过 SSH 真正执行同样的同步。目标是 root@127.0.0.1:/root/sync/dst1/,端口为 2222,密钥为 /root/.ssh/id_labhub。完成后 /root/sync/dst1/app/main.py 必须存在。

rsync 有一个选项,可以整体指定远程 shell 命令。请把端口和密钥放进去。

验证末尾斜杠的差异

验证末尾斜杠的差异。把 /root/sync/src(没有斜杠)发送到 /root/sync/dst2/ 时,必须生成 /root/sync/dst2/src/app/main.py。

把同一个源只改变斜杠的有无,分别发送到两个目标,比较结果的结构。

带保护的 --delete

编写 /root/sync/backup.sh 脚本。它要以 set -euo pipefail 开头,包含在源目录为空时以退出码 1 中止的检查,并使用 --delete 把 /root/sync/src/ 同步到 /root/sync/dst3/。源路径要以第一个参数接收,没有参数时使用 /root/sync/src/——评分器会把空目录作为第一个参数传入,确认保护措施真的起作用。运行脚本,创建 /root/sync/dst3。

请在脚本开头加入源目录为空时立即中止的检查。同时加上 set -euo pipefail。

应用排除规则

排除 logs/ 之下的内容,把 /root/sync/src/ 同步到 /root/sync/dst4/。/root/sync/dst4/logs 不得存在。

排除模式可以指定多次,也可以从文件中读取。目标中不能有日志文件。

硬链接多代备份

创建多代备份。先完整同步到 /root/sync/gen/daily.1/,再用 --link-dest 创建 /root/sync/gen/daily.0/。未变更的文件在两代之间必须共享同一个 inode。

--link-dest 如果给的是相对路径,会以目标为基准来解释。绝对路径更安全。用 stat 的链接数来确认。

证明同步已完成

把 /root/sync/final.txt 写成下面这 3 行。 PENDING=<3번과 같은 동기화를 다시 dry-run 했을 때 전송 예정 파일 수> / DST4_HAS_LOGS=no / SHARED_INODE=yes(第一项的占位符为再次对与第 3 步相同的同步执行 dry-run 时预定传输的文件数) PENDING 必须为 0。

如果同步正确,用 dry-run 再次运行同一条命令时,应当没有需要传输的内容。