Featured image of post 使用 rsync 进行同步

使用 rsync 进行同步

一篇对 rsync 使用方法的简单记录

有点受不太了 scpsftp 了,也许是食用姿势不对吧,总之我选择 rsync

图源找不到诶……从朋友那里薅过来的图,很漂亮就放在这里了。既然如此就分享一首钢琴曲吧。一首 騎士王の誇り (骑士王的荣耀) 送给大家。

为什么要选择 rsync 呢?

有时候我们有多个远程电脑,或者是服务器,上面的文件内容我们希望下载到本地。我们通常有这么几个选择:使用一些功能成熟的,专用于 SSH 连接的终端模拟器,比如 MobaXTerm 这样的软件;或者我们可以使用 scpsftp 这样的工具,但是界面有点简陋,特别是 sftp,需要反复确认文件名是否输入错误。而且有时我们只需要下载不同的部分,不希望重复下载已经有了的部分。这时候,rsync 作为 remote sync 的工具,就到了发挥其作用的地方了。

使用方法

命令结构

rsync 命令使用方法是:

1rsync --option1 --option2 /pass/files/from/this/ /path/files/to/here

所以大概就是遵循:命令,选项,从哪里来,到哪里去 这样的规则。另外,既然 rsyncremote sync 的简称,自然这个命令也是可以被用于远程服务器之间的文件传输的。方法也很简单,就是给对应的文件路径添加上使用 ssh 的用户名、服务器地址等信息。具体用法我们下面介绍。

注意路径分隔符 /

首先,这里需要强调的是,请注意 从哪里来,也就是发送端的这一部分,这里明显是一个文件夹,因为路径的最后有一个 / 符号。也许有人会问:我知道它是文件夹,我能不要那个 / 吗?比如使用

1rsync --opt1 --opt2 /pass/files/from/this /path/files/to/here

这样的命令,来把文件夹传过去,可以吗?

答案很有趣:是的,你可以传过去,但是也许不会以你预期的方式传过去。由于 rsync 会默认传过去的位置是个文件夹,如果你不带上这个斜杠的话,rsync 会认为你打算把 /pass/files/from/this 这个文件夹 放在目标位置的里面。如果你的确打算这么做,那没什么问题。比如你在本地有一个文件夹 $HOME/mydocuments,你在远程的服务器的接收端上也有这么个文件夹,位置一模一样,那么就可以尝试

1rsync -r $HOME/mydocuments me@remote:/home/me

这会直接把 $HOME/mydocuments 传到远程的 /home/me 文件夹下,形成 /home/me/mydocuments 这样的结构。

那么假如你是想说,我要把 $HOME/mydocuments 里面的内容 传到 /home/me/another/position 的话,那你就需要带上这个斜杠了,因为 rsync 就会聪明地帮你把文件夹里面的所有内容传到目标位置的那个文件夹里。也许也算是符合 “一切皆文件” 的思想了吧,如果你不带分隔符,就会以文件形式把这个 文件 传到文件夹里;而如果带上路径分隔符,则说明你要传的是文件夹的内容。

远程链接

作为一款远程同步软件,自然需要有办法告诉 rsync 要把文件从哪里发到哪里。好消息是,rsync 支持我们通过 SSH 传输文件,而方法也特别简单。只需要在文件路径前面添加上你的用户名和主机名就可以了。如果你设置了 SSH 的主机名,甚至可以更方便。

这里举个很简单的例子,从本机传到本机,但是通过 SSH 进行。我们可以通过 ssh <user>@localhost 来登录到本机的本地账户上,我的用户名是 amoment,所以就会用 ssh amoment@localhost 来登录到本机。那么我们就可以这样告诉 rsync

1rsync -r /home/amoment/myfiles/ amoment@localhost:/home/amoment/somefolder

来把我家目录下的 myfiles 文件夹里的内容复制/同步到同在家目录下的 somefolder 文件夹下。有了这个例子,你应该也明白怎么跨设备使用 rsync 通过 SSH 进行连接与文件传输了吧。

除了使用 SSH 协议以外,rsync 还支持一些其他的协议,比如所谓的 RSH,或者 rsync 自带的 rsync:// 协议。但是由于 SSH 的支持还是更加广泛,我们这里还是只介绍该方案。如果感兴趣的话,可以查阅 rsync 的手册或者文档等资料。

一些重要的参数

下面列举一些重要的,可能会经常使用到的参数。我们按一个大致的类别做区分,方便查找。

文件操作

  • -r --recursive: 递归模式

它的意思是 recursive,也就是递归地把所有内容都传过去。如果不加这个东西,会发生什么呢?好消息是你照样能完成传输,但是坏消息是,你 只传过去了文件夹。也就是说,如果你不是只想在目标位置创建一个可能是新的文件夹的话,而是想把文件都传过去,请记得带上 -r

  • -a -- archive: 存档模式

你也可以选择不使用 -r 而是使用 -a,使用 -a 会以存档方式传输文件,也就是说,文件夹内的所有东西都会 保持原样 地传过去:不论是文件,文件夹,还是链接,设备描述符等,全都会原样传过去。-a 实际上是一系列参数的总和。根据帮助文档所述,是 -rlptgoD。还挺多的……

  • --delete: 允许删除不同步的内容

因为 rsync 如其名所示,是 同步软件,因此我们也许希望不是 “上传” 文件,而是 把本地文件结构同步到远程。此时,我们需要用到 --delete 这个参数,它给了 rsync 删除目标文件夹内多余文件的权利,从而保证你确实是在 同步 内容。

  • --exclude --include: 按模式进行排除/包含

这两个参数我们放在一起讲。如其名称所述,是用来告诉 rsync 排除哪些文件或者包含哪些文件用的。如果你有些文件不想传/特意要传,请设置这两个参数。

  • --ignore-existing: 跳过传输同名文件

加上这个参数会让 rsync 检查接收端已有文件的名字,如果本地和接收端都有这么个文件(名称相同),则会跳过这个文件不进行传输。

  • -u --update: 只传输更新的内容

这个参数意味着你是打算 更新 文件们。那么,如果接收端的文件比发送端更新(还要新)呢?答案就是不会碰这些文件。

  • -z --compress: 先压缩一下

这个参数会告诉 rsync 传输前先帮你把要传的东西压缩一下。rsync 会自己选择一个压缩方法,所以一般不用担心。

信息提供

  • -n --dry-run: 试运行

你要是担心传过去的内容不是你实际打算传的东西,你可以先让 rsync 告诉你目前的命令会传些什么,且不真的开始工作,只需要加上 -n 就可以。你可以把它理解为 no,即便实际上它对应的长参数是 --dry-run。拿不准会传些什么过去的时候,这个命令会很有用。

  • -v --verbose: 更啰嗦一些

几乎所有(较复杂)的命令行程序都会内置这样一个命令,来把工作信息 “更啰嗦” 地显示出来。如果你需要额外的信息,请使用这个参数。

  • -P: 进度条

就是让 rsync 报告当前的传输进度。我很喜欢用。

涉及 rsync 本身 / 远程协作

  • -e --rsh: 指定传输协议

可能我们要传输的设备开放的 SSH 端口不在默认的 22 而是一个自定义的端口。此时我们就需要 -e 然后在后面带上一个字符串来表示使用的 shell 是哪个。比如我的远程接收端接口是 1145,则我会使用

1rsync -r -e "ssh -p 1145" /myfiles/ me@remote:/myfiles

来让 rsync 尝试使用 1145 端口进行 SSH 通信与文件传输。

  • --rsync-path: rsync 在哪?

有可能我们需要帮助本地的 rsync 来寻找到另一个 rsync 究竟在哪。此时我们就需要这个参数来发挥作用,在后面带上找到 rsync 的方法:不论是 rsync 的路径,还是别的方式,都可以。比如希望传输的设备有 rsync,但是在 WSL 上。此时我们就可以

1rsync -r --rsync-path 'wsl rsync' me@remote:/myfiles/ /myfiles

来让远程使用 WSL 上的 rsync 为我进行工作。

后记

我一开始使用 rsync 的主要理由其实是为了在不同的设备之间同步我的歌曲库。由于我有一些歌曲通过移动硬盘已经移动了一部分,而还有一部分没有同步,在另一台电脑上我甚至新添加了一张专辑,所以感觉单纯地自己手动搜索要迁移的文件有点太累了。而此时,rsync 用它 增量同步 的特性吸引了我,我便使用这么个方式来把远程的歌曲同步到本地电脑上来。

rsync 还是挺好用的,它的语法可能没有那么智能,但是已经足以应付我遇到的问题了。印象中还有一些别的同步软件,比如朋友推荐的 Syncthing,也许后面会尝试使用一下。

另外不得不提的是我在准备该文章时查阅过的信息源。非常感谢!

  • 首先,ChatGPT 和 Deepseek,完全不了解的时候和这些 AI 问一下还是挺好用的;
  • rsync tutorial: 一个简单的 rsync walkthrough,帮了我很多;
  • rsync command in Linux with Examples: GeeksForGeeks 下的一个博客,内容很丰富。

最后,感谢您能看到这里,祝您身体健康,心情愉悦~