Duplicacy 是一个开源的,基于无锁去重算法开发的云备份工具,他的核心思路类似 Git 等版本控制软件

  • 多台电脑可以备份 / 同步到同一 (云) 储存 (类似远程 Repo 和本地 Repo 的关系)
  • 可以将工作区还原到任意一个 Revision (类似把 Origin 切换到任意一个 Commit)
  • 支持文件加密,压缩,打包,快照,同步云服务等功能

Duplicacy 直接支持下面这些 (云) 存储方式

  • Local disk
  • SFTP
  • Dropbox
  • Amazon S3
  • Wasabi
  • DigitalOcean Spaces
  • Google Cloud Storage
  • Microsoft Azure
  • Backblaze B2
  • Google Drive
  • Microsoft OneDrive (支持 Personal, Business, 不支持世纪互联)
  • Hubic
  • OpenStack Swift
  • WebDAV (under beta testing)
  • pcloud (via WebDAV)
  • Box.com (via WebDAV)
  • File Fabric by Storage Made Easy

Rclone 是一个用于多个云平台之间同步文件和目录的命令行工具,他的定位于 Duplicacy 不同

  • 支持将本地文件以 Sync, Move, Copy 等方式直接上传到云储存
  • 支持利用 VFS 技术将云储存挂载为本地磁盘
  • 支持 OneDrive 世纪互联

本文将利用 Rclone 的 VFS 虚拟磁盘,配合 Duplicacy, 实现小文件高效备份到 OneDrive 世纪互联的效果

# Rclone

# 下载

首先我们要下载并配置 Rclone, 这里我们以 Windows 和 Linux 为例

# Windows

首先,我们要在 Github 下载二进制文件,读者需要选择合适的架构,这里我们选择 amd64

下载后将二进制文件改名为 rclone.exe, 丢入 C:\Windows\System32

为了后文挂载虚拟磁盘,Windows 系统需要安装 WinFSP 来提供 VFS 的功能,下载后按照步骤安装就可以了

如果读者有安装过天翼云盘,那么就不必再次安装 WinFSP 了,安装天翼云盘的时候会自动帮你安装好 WinFSP

# Linux

curl https://rclone.org/install.sh | sudo bash

为了后文挂载虚拟磁盘,Linux 需要安装 fuse, 请根据发行版选择正确的安装方式

# Debian/Ubantu
apt-get update && apt-get install -y fuse
# CentOS
yum install -y fuse

在任意位置打开终端,输入 rclone, 应该已经能看到帮助信息了

# 配置存储库

# 创建 Azure 应用

这里我们将使用 Rclone 在本地挂载远端 OneDrive, 然后使用 Duplicacy 在虚拟磁盘中创建存储库

我们首先需要先配置 OneDrive 的相关鉴权行为,允许 Rclone 访问我们的 OneDrive.

访问 https://portal.azure.cn/ 登录完成后按下面步骤进行

  1. 访问 https://portal.azure.cn/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade -> 点击新注册

  2. 名称:任意名称 -> 受支持的账户类型: 任何组织目录 (任何 Azure AD 目录 - 多租户) 中的帐户 -> 重定向 URI: http://localhost:53682 -> 注册

image.png

  1. 注册后请记住并保存这里的 应用程序 (客户端) ID, 这是我们一会要用到的 client_id

image.png

  1. 点击左侧的 API 权限 -> 点击蓝色的 Microsoft Graph (1) -> 在搜索框中搜索并允许下面这些权限
Files.Read
Files.Read.All
Files.ReadWrite
Files.ReadWrite.All
offline_access
User.Read

勾选后,应该是这样的效果

image.png

  1. 点击左侧的证书和密码 -> 新客户端密码 -> 任意输入说明 -> 截止期限选 24 个月 -> 点击添加

  2. 添加后请记住并保存这里的 ,这是我们一会要用到的 client_secret

image.png

# 添加 Rclone 远程存储库

  1. 在任意位置打开终端,输入 rclone config , 输入 n 新建一个远程存储库

  2. name> 输入一个你喜欢的名称 (这个名称也会成为挂载后的磁盘名称)

  3. Storage> 根据提示,找到 Microsoft OneDrive 的序号并填入

  4. client_id> 填入我们上文刚刚获取到的 client_id

  5. client_secret> 填入我们上文刚刚获取到的 client_secret

  6. region> 这里选择 Azure and Office 365 operated by Vnet Group in China 的序号

  7. Edit advanced config? 这里输入 n, 不进行进阶的配置

  8. Use auto config? 这里输入 y, 自动进行 Token 获取

  9. 接下来,浏览器应该会弹出世纪互联账户的登录页面,按照要求进行登录就可以了

  10. Your choice> 这里输入 1, 使用常规的 OneDrive Personal or Business

  11. Chose drive to use:> 这里输入 0, 因为只能输入 0 (bushi

  12. Is that okay? 这里确认一下输入的信息无误后,输入 y

  13. 接下来 Rclone 会进行自动获取 Token 生成配置文件的过程,当获取完毕后,会再次让你确认是否无误,输入 y 确认

  14. 确认后应该已经能看到自己新配置的存储库了

image.png

# 挂载虚拟磁盘

在任意位置打开终端,输入 rclone mount <存储库名称>:/ Z: , 应该就能在资源管理器中看到刚刚挂载的 Z 盘了

当我们关闭终端或者 Ctrl+C 结束当前命令的时候,挂载的盘符消失

关于 rclone mount 的缓存相关配置,可以阅读下面笔者的扩展阅读部分,这里仅给出笔者的配置作为参考

如果要使用 Duplicacy, 请务必保证缓存目录的剩余空间大于要备份文件的总大小

rclone mount OneDrive:/ Z: --cache-dir <缓存目录> --vfs-cache-mode writes --vfs-cache-max-size 30G --vfs-cache-max-age 1h

接下来我们要配置后台执行和开机启动,这里我们以 Windows 和 Linux 系统为例

# Windows

这里我们使用 WinSW 来配置 Windows 自动启动服务,在 Github 下载 WinSW

下载后将二进制文件改名为 winsw.exe, 放到 rclone 的配置文件所在目录 (% AppData%\rclone)

在相同的目录创建 rclone-mount.xml, 填写以下内容

需要注意,这里 rclone 的配置文件需要手动指出,这里笔者已经填入了默认配置文件的位置,--config 参数不可删除

<service>
    <id>rclone</id>
    <name>rclone</name>
    <description>This service run rclone mount network file systems to local disk</description>
    <executable>rclone</executable>
    <arguments>mount OneDrive:/ Z: --config %BASE%\rclone.conf --vfs-cache-mode writes --vfs-cache-max-size 30G --vfs-cache-max-age 1h</arguments>
    <log mode="roll"/>
</service>

使用终端打开当前目录,输入 winsw install rclone-mount.xml

现在,这个目录的结构大概应该是这样的,同时,如果读者打开资源管理器,应该已经看到挂载的盘符了

image.png

# Linux

Linux 推荐使用 systemctl 配置开机自启服务,这里我们创建 rclone-mount 服务

vi /usr/lib/systemd/system/rclone-mount.service

填入并按需修改以下内容

[Unit]
Description=This service run rclone mount network file systems to local disk
After=network.target
[Service]
Type=simple
User=root
ExecStartPre=/bin/sh -c 'until ping -c1 baidu.com; do sleep 1; done;'
ExecStart=rclone mount OneDrive:/ /mnt/OneDrive --allow-other --allow-non-empty --vfs-cache-mode writes --vfs-cache-max-size 30G --vfs-cache-max-age 1h
ExecStop=fusermount -u /mnt/OneDrive
[Install]
WantedBy=multi-user.target

之后,我们配置服务的开机自启: systemctl enable rclone-mount.service

# Duplicacy

# 下载

接下来我们下载 Duplicacy, 这里我们依旧以 Windows 和 Linux 为例

# Windows

下载后将二进制文件改名为 duplicacy.exe, 丢入 C:\Windows\System32

# Linux

wget -O /usr/local/bin/duplicacy https://github.com/gilbertchen/duplicacy/releases/download/v3.2.3/duplicacy_linux_x64_3.2.3
chmod 0755 /usr/local/bin/duplicacy

在任意位置打开终端,输入 duplicacy, 应该已经能看到帮助信息了

# 配置存储库

Duplicacy 把位于计算机本地的待备份目录称为 Repository, 这里笔者在 E 盘创建了一个名为 Vault 的文件夹,我们接下来将对这个文件夹进行备份

首先,我们需要先切换到 Vault 文件夹中,并且创建 Duplicacy 的仓库,这里 vault 为仓库的标识名,后面的路径为远程库的路径

这里我们使用上文创建好的 Rclone 虚拟磁盘作为远程库.

cd E:\Vault
duplicacy.exe init -c 128M -min 32M -max 1024M vault Z:\Vault

Duplicacy 使用 Hash 块来储存打包后的文件,我们通过 - c -min -max 参数来指定单个块的大小.

块过小会导致文件零散,上传时性能比较低,块过大会导致微小的更改就需要重建整个块,这里请读者根据需要进行修改.

如果读者的数据不常修改,推荐使用稍大一些的块

# 进行备份

备份的线程越多,占用的 CPU 和内存越多,备份速度越快.

这里 32 线程已经能吃到 16G 以上的内存,请读者酌情配置.

cd E:\Vault
duplicacy.exe backup -threads 32

# 更多操作

这里笔者就不过多介绍 Duplicacy 了,如果读者希望进一步了解使用,欢迎阅读其他博主的文章.
Duplicacy CLI 备份工具的基本使用: https://blog.dejavu.moe/posts/duplicacy-cli-basic-guide/

# 扩展阅读

# Rclone 传输优化

当传输大文件时,为了让 Rclone 的传输速率达到最大,这里我们可以配置下面几个参数

要注意的是,过度拉高这些参数可能会导致高内存占用,不建议在 VPS 等性能较弱的机器上调整

# --cache-chunk-size

The size of a chunk (partial file data).

Use lower numbers for slower connections. If the chunk size is changed, any downloaded chunks will be invalid and cache-chunk-path will need to be cleared or unexpected EOF errors will occur.

# --transfers

文件并行数量,不建议设置太多,即使多线程,也受 OneDrive 的速度限制,这里建议测试一下,寻找能达到最大速度的最少线程数

# --onedrive-chunk-size

Onedrive 的 chunk-size 设置 必须是 320KB 的倍数,取 100MB 适合 G 口服务器,如果我们的接口速率达不到那么大,没必要设置的太大

这里笔者仅给出自己的配置作为参考

rclone sync Vault OneDrive:Vault -P --cache-chunk-size 4M --transfers=16 --onedrive-chunk-size 10240

# Rclone VFS 优化

rclone mount 关于缓存方式有下面几个参数,我们这里直接对重要的几个参数进行讲解

# --vfs-cache-mode

vfs-cache-mode: 虚拟磁盘的缓存方式,主要有下面几种选择

  • --vfs-cache-mode off: 所有读取和写入都直接操作远程
  • --vfs-cache-mode minimal: 只读和只写打开的文件直接从远程读取,读 / 写的文件首先缓冲到磁盘.
  • --vfs-cache-mode writes: 只读打开的文件直接从远程读取,只写和读 / 写的文件首先缓冲到磁盘.
  • --vfs-cache-mode full: 所有读取和写入都缓冲到磁盘

off < minimal < writes < full, 需要注意的是,OneDrive 只支持大于等于 writes 的模式

这里更为详细的介绍推荐阅读官网的相关文档: https://rclone.org/commands/rclone_mount/

这里笔者只针对几个情形进行针对性的讲解和分析:

  • writes 模式:适合磁盘空余空间较大的读者,适合除了 Duplicacy 备份,还想平常使用 OneDrive 的读者。当使用 writes 模式向 OneDrive 上传文件时,这些文件会首先储存在本地 VFS 的缓存目录中慢慢上传,等文件全部上传到云端后,再释放掉缓存。这会导致如果用户第一次使用 Duplicacy 备份 100G 的文件时,缓存目录会先占满约 100G 的空间,再慢慢释放.

  • off 模式:适合磁盘没有空余空间的读者,或者要备份的文件占用空间过大的读者。但可惜 OneDrive 不支持流式传输,所以读者在使用 OneDrive 时不能选择这个模式

# --vfs-cache-max-size

当启用缓存时,文件缓存的最大占用空间。这个最大空间限制只对从远端读取时生效,例如,如果你向网盘中复制 100G 的文件,缓存目录会先占用约 100G 的空间,然后再慢慢释放

# --vfs-cache-max-age

当启用缓存时,文件缓存的最大存活时间。这个最大时间限制只对从远端读取时生效,例如,如果你观看网盘中的电影,Rclone 会从网盘中边下边播这部电影,在超过存活时间后,再次观看,又要从头开始重新下载

# --buffer-size

设置内存缓存大小,这里如果日常使用建议 100M 左右就够了,如果只作为 Duplicacy 备份使用,那建议不配置

# --cache-dir

文件缓存的目录,如果不设置,默认目录为 C:\Users\chenb\AppData\Local\rclone\

如果要使用 Duplicacy, 请务必保证缓存目录的剩余空间大于要备份文件的总大小

这里笔者仅给出自己的配置作为参考,注意 --vfs-cache-mode 参数在使用 OneDrive 时必须大于等于 writes

rclone mount OneDrive:/ Z: --vfs-cache-mode writes --vfs-cache-max-size 30G --vfs-cache-max-age 1h

# Duplicacy 世纪互联

Duplicacy 论坛有这样一个帖子: https://forum.duplicacy.com/t/add-support-for-onedrive-business-china/3869

这个博主只是修改了登录的 Entrypoint, 没有修改 client_id, 因为 Duplicacy 在世纪互联没有注册相应的应用,必然不能用

我们按照上文的方法创建自己的 client_id 并授予响应的权限、打开响应的回调 URL 后,再次尝试。这次我们成功从微软相关网站跳转到了 Duplicacy 的 odb_start 页面,但是 odb_start 无法获取到相应的 token 和 refresh_token. 因为 OAuth 回访获得 token 也需要传入对应的 client_id, client_secret, 但是 odb_start 中没有实现用户侧填写这些信息.

再次整理后,我们发现,可以手动获取 token, refresh_token 并且填入 json 中,将 json 提供给 Duplicacy. 但由于 refresh_token 的过程仍需响应的 client_id, client_secret. 这意味着我们需要使用外部的一个程序负责给 Duplicacy 获得的 token 进行续约操作。这种操作比较复杂.

希望 Duplicacy 早日提供支持世纪互联的接口,或者将 client_id, client_secret 侧做的更灵活.