坑边闲话:早年笔者一直以为网盘只能通过官方客户端使用,然而官方客户端并不好用。最近一两年,网盘的本地挂载越发成熟,海内外的网盘公司纷纷推出 OpenAPI,允许第三方开发者使用网盘。将 OpenAPI 和 libfuse/winfsp 结合起来就可以实现网盘的本地挂载,基本可以像操作本地文件一样操作网盘里的数据,特别是在只读场景。本文详细介绍商业软件 CloudDrive2 的使用方法。

1. 安装与配置·

CloudDrive2 是一个以网盘本地挂载为卖点的商业软件,虽然目前还处于 0.x 版本,但它已经有了很强的可用性,而且在笔者半年的使用时长中表现非常稳定。

不过要注意,并非所有网盘都支持本地挂载,也并非所有网盘都提供 Open API 允许开发者折腾。比如知名的百度网盘就没有 Open API, 现有的挂载功能基于对百度网盘的协议逆向。

1.1 Windows 与 macOS·

Windows 需要打开 19798 端口的防火墙入站。对于 macOS,需要进入 Recovery 模式,临时关闭 SIP 以安装 macFUSE,随后即可重新启用 SIP.

Windows 本地挂载体验非常良好,但是 macOS Finder 回爆发性地收集文件元数据、计算缩略图,有可能导致网盘目录卡死。在 macOS 上尽量不要使用 Finder 进行操作。

1.2 Linux·

笔者以 Debian 13 为例进行讲解。由于 CloudDrive 官方仅提供编译好的二进制,而且没有提供安装包,因此需要手动下载、解压,并创建系统后台驻留进程。

1.2.1 安装最新版本·

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bash -c '
CD2_VERSION=0.9.21
ARCH="x86_64"
CD2_URL="https://github.com/cloud-fs/cloud-fs.github.io/releases/download/v${CD2_VERSION}/clouddrive-2-linux-${ARCH}-${CD2_VERSION}.tgz"

curl -L -o /tmp/clouddrive2.tgz "${CD2_URL}"
tar -xzf /tmp/clouddrive2.tgz -C /tmp/
sudo mv /tmp/clouddrive-2-linux-${ARCH}-${CD2_VERSION} /usr/local/bin/
sudo mv -f /usr/local/bin/clouddrive-2-linux-${ARCH}-${CD2_VERSION}/ /usr/local/bin/clouddrive
sudo chown -R root:root /usr/local/bin/clouddrive
sudo chmod +x /usr/local/bin/clouddrive/clouddrive
rm -f /tmp/clouddrive2.tgz
echo "CloudDrive2 installation done"
'

1.2.2 创建 systemd 启动项·

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
sudo tee /etc/systemd/system/clouddrive2.service > /dev/null << EOF
[Unit]
Description=CloudDrive2 Mount Service
After=network-online.target
Before=docker.service
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/clouddrive/clouddrive
Restart=always
RestartSec=5
User=root
StandardOutput=journal
StandardError=journal

ExecStartPre=/bin/mkdir -p /mnt/CloudDrive

[Install]
WantedBy=multi-user.target
EOF

1.2.3 启动服务·

随后启用 systemd 服务即可。

1
sudo systemctl enable --now clouddrive2.service

2. WebDAV 服务与本地挂载·

在高延迟场景下,特别是跨洲场景,SMB/NFS 等协议由于频繁的元数据同步会变得非常卡。然而大多数时候我们仅仅是想访问很少的文件,为此需要一个轻量化的文件共享协议,既能让我们浏览目录,又能让我们读写文件。WebDAV 就是这样一种简单的协议:

  • 单端口即可完成服务;
  • 可以挂载到本地(需要使用第三方软件);
  • 没有频繁的元数据同步,特别适合偶尔上传、下载少量文件的场景。

图 1. CloudDrive2 的 WebDAV 服务器配置界面。

CloudDrive2 即是 WebDAV 服务器,又可以充当 WebDAV 客户端。

  1. 在服务器上启用 CloudDrive2 的 webdav 功能
  • 添加专用的 webdav 用户或者直接使用 CloudDrive2 账号。
  • 每个账号都有自己可见的虚拟根路径以及对根路径的读写权限预设。建议使用最小权限原则。
  1. 在客户端的 CloudDrive2 界面添加 WebDAV 类型的云存储,填入服务器的验证信息并登录。
  2. 随后可以选择将该云存储挂载到本地,方便后续使用。

上述第三点是 CloudDrive2 绝妙的一个设计,它彻底打通了外源存储的本地挂载多机存储互联的所有障碍,从此一台服务器的存储可以通过 WebDAV 出现在另一个机器的某个目录上。

图 2. 在扮演客户端角色的 CloudDrive2 设置界面添加云存储,并选择 WebDAV.

3. 云盘本地缓存·

自从 0.9.18 版本起,CloudDrive2 支持云盘文件的本地缓存,用户可以在本地存储中划分一定配额,让 CloudDrive2 用来进行文件缓存。缓存语义如下:

云盘文件和本地文件建立一一映射。本地缓存以 HASH_64_HEX.cache 命名。哈希值计算方法目前不详,非直接从云盘获取的 SHA256,也并非云盘文件添加前缀、尾缀之后的 SHA256.

经过二进制对比,发现 CloudDrive2 会给文件添加前缀

1
2
3
4
00000000: 4344 4643 4143 4845 0200 0000 5876 6300  CDFCACHE....Xvc.
00000010: 0000 0000 0100 0000 0000 0000 0000 0000 ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................

以及后缀

1
2
00637690: **** **** **** **** 0000 0000 0000 0000  *******.........
006376a0: 5876 6300 0000 0000 Xvc.....

前后缀用来增加 cache 文件的辨识度。此外,文件哈希计算基于某种静态算法,和客户端、网盘提供商并不绑定,因此可以夸网盘、跨用户、跨客户端使用。

目前来看,该文件是一个稀疏文件。当用户首次读取云盘上的某个文件时,CloudDrive2 会根据某种哈希算法创建与之对应的本地缓存文件。该缓存文件在初始阶段属于全 hole 文件,即所有的块都是 0000. 随后,当具体的数据从云端读被读取出来之后,CloudDrive2 会同步地在该文件的对应偏移处进行写入该数据。用户再次读取该文件偏移据时,CloudDrive2 将直接以缓存文件的内容进行反馈。

因此,在不依赖文件系统语义的情况下,理论上 CloudDriv2 应该会维护一个本地的文件 bitmap,用来记录缓存文件里哪些是真实的块,哪些是 hole. 然而 CloudDriv2 声称该缓存文件可以随意转移,这意味着该 bitmap 有可能事实上并不存在。如果确实不存在,CloudDrive2 是如何区分 hole 与真实的 0000 记录的呢?毕竟很多 copy 工具会在拷贝时把 hole 彻底 0 化,变成真实的 0 块。所以笔者猜测,随意转移这句话在工程上通常隐含前提:用能保稀疏的方式迁移。当然,纯单机、本地使用在没有 bitmap 的情况下问题不大,因为 CloudDrive2 可以调用 lseek(SEEK_HOLE) 找 hole.

此外,如果某文件在云端被修改,但是云盘没有通知 CloudDrive2 客户端要同步缓存,这也会导致严重的数据不一致问题。

在上述两个问题研究清楚之前,该缓存方案应该仅被谨慎地应用于只读类型的文件。

to be continued.