使用 Rclone 挂载网盘

2020-02-01 • 更新于 2023-09-27

在没有图形界面的服务器上,或不想使用客户端软件时,如何方便地使用网盘是个问题。

Rclone 就是为此而生的,它可以方便在命令行下挂载网盘,目前已经支持包括 Google Drive、OneDrive 在内的几十个网盘,而且除了速度慢一点外,可以模拟本地磁盘,对于容量有限的 VPS 来说就是免费扩容,配合 aria2、Transmission 等工具,就可以打造离线下载服务器。

配合 aliyundrive-webdav 项目,可以以 WebDAV 方式挂载阿里云盘。阿里云盘国内速度很不错,但国外就不太理想了,适合用作本地服务器备份、在线播放电影等。支持上传文件,但受限于 WebDAV 协议不支持文件秒传。

安装

Debian 的官方源中 Rclone 版本过于陈旧,建议到官网下载:https://rclone.org/downloads/

或者脚本一键安装:

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

阿里云盘(2023 更新)

以下以 Debian 为例,运行阿里云盘 WebDAV 服务并使用 Rclone 自动挂载。

aliyundrive-webdav

首先安装 aliyundrive-webdav:

# pip install aliyundrive-webdav

我讨厌虚拟环境,因为它总是把东西封装得面目全非,所以这里用特权用户安装,而且方便之后编写 systemd 脚本。根据个人喜好即可。

获取 token:

# aliyundrive-webdav qr login

手机打开阿里云盘 APP 扫码得到 token。

为 WebDAV 服务专门建立一个目录,用于存放 token:

# mkdir /var/lib/private/aliyundrive-webdav
# vim /var/lib/private/aliyundrive-webdav/refresh_token

将 token 复制到 refresh_token 文件中。

新建 systemd 脚本:

# cat /etc/systemd/system/aliyundrive-webdav.service
[Unit]
Description=Aliyun Drive WebDAV Service
After=network-online.target

[Service]
DynamicUser=yes
StateDirectory=aliyundrive-webdav
ExecStart=/usr/local/bin/aliyundrive-webdav --host localhost --workdir "$STATE_DIRECTORY" --cache-ttl 10

[Install]
WantedBy=multi-user.target

/var/lib/private 是个特殊的目录。

systemd 脚本如果指定了 StateDirectory,就会从 /var/lib 寻找目标文件夹,通过 $STATE_DIRECTORY 来访问它。但如果同时指定了 DynamicUser=yes,就会在 /var/lib 建立一个软链接指向 /var/lib/private 中的同名目标文件夹:

# ll /var/lib/aliyundrive-webdav
lrwxrwxrwx 1 root root 26 Mar 21 16:48 /var/lib/aliyundrive-webdav -> private/aliyundrive-webdav

由于只有特权用户能访问 /var/lib/private,以此保证了安全性,这就是上面建立 /var/lib/private/aliyundrive-webdav 目录的原因。

aliyundrive-webdav 通过 --workdir 参数指定工作目录,就可以读取和更新 token 了。

# systemctl daemon-reload
# systemctl start aliyundrive-webdav.service
# systemctl enable aliyundrive-webdav.service
# systemctl status aliyundrive-webdav.service

/etc/fstab 自动挂载

Rclone 可以作为 Unix mount helper 实现 mount 命令的挂载:

# ln -s /usr/bin/rclone /sbin/mount.rclone

还可以添加到 /etc/fstab 中,这就很方便了,不需要写什么蛋疼的 systemd 脚本。

不过这一方法需要 fuse3(rclone mount 似乎 fuse2 就行 新版 rclone mount 也需要 fuse3 了):

# apt install fuse3
# vim /etc/fuse.conf

取消注释 user_allow_other,以允许其他用户访问挂载目录。

添加挂载项:

# mkdir /mnt/aliyun
# cat <<-END >>/etc/fstab
# https://rclone.org/commands/rclone_mount/#rclone-as-unix-mount-helper
:webdav: /mnt/aliyun rclone nofail,_netdev,args2env,webdav_url=http://localhost:8080,allow_other,vfs_cache_mode=full,vfs_cache_max_age=24h,cache_dir=/var/cache/rclone,config=/dev/null 0 0
END

第四列是关注的重点,各选项以 , 分隔,例如,需要以指定用户挂载,可以添加 uid=xxx,gid=xxx 选项。

注:

Debian 从最近(2023 年 9 月前后)某次更新后,原本第四列的 x-systemd.automount 将会导致 Fatal error: mount not ready,如果此时访问目录则会报错 Transport endpoint is not connected,原因不明,因此删去这个选项。

这个选项的作用是让目录在实际访问时挂载(延迟挂载),而不是开机就立即启动。

如果有其它需要的 rclone 参数也可以添加,但 GNU 风格的参数要手动翻译一下,前缀 -- 去掉,- 改为 _,例如 --vfs-cache-mode=full 要改为 vfs_cache_mode=full

看看成功了没有:

# mount -av

需要 debug 的话,在第四列添加 vv 以查看更详细的 log。

这一配置会自动挂载,而且只有在访问挂载目录时真正挂载。

OneDrive(写于 2020 年,可能已过时,仅供参考)

Rclone 提供了简单的交互式配置方式,运行 rclone config 即可,一般就是打开浏览器获取一个 token,网上有很多教程,在此就不赘述了。

以 OneDrive for Business 为例,主要说明一下如何在没有图形界面的情况下获取 token。

一种是先用其他带图形界面的系统配置一次,直接把 token 复制过去。

另一种就是在命令行下执行到这一步时:

Use auto config?
 * Say Y if not sure
 * Say N if you are working on a remote or headless machine
y) Yes
n) No
y/n> y
If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth?state=xxxxxxxxxxxxxxxxxxxxxx
Log in and authorize rclone for access
Waiting for code...

选择 y 的话理论上会打开浏览器访问那个地址,当然由于是服务器,不可能打开浏览器,这时我们重开一个 SSH 连接,并用 curl 访问:

$ curl http://127.0.0.1:53682/auth?state=xxxxxxxxxxxxxxxxxxxxxx
<a href="https://login.microsoftonline.com/common/oauth2/v2.0/authorize?access_type=offline&amp;client_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;redirect_uri=http%3A%2F%2Flocalhost%3A53682%2F&amp;response_type=code&amp;scope=Files.Read+Files.ReadWrite+Files.Read.All+Files.ReadWrite.All+offline_access&amp;state=xxxxxxxxxxxxxxxxxxxxxx">Temporary Redirect</a>.

复制 href 中的链接,对其 URL 解码,可以使用 Python 或其它工具,如:https://tool.chinaz.com/tools/urlencode.aspx

接着(客户端)使用浏览器访问解码后的 URL 并登陆账号,然后会重定向到一个本地 URL,在服务器上用 curl 访问此 URL。

这时 Rclone 的配置应该会自动进行到下一步,其它照常配置即可。如果不行就多试几次。

挂载

安装 FUSE:

$ sudo apt install fuse

将名为 onedrive 的配置挂载到 /mnt/onedrive 下:

$ rclone mount onedrive:/ /mnt/onedrive --vfs-cache-mode full --vfs-cache-max-age 24h --vfs-cache-max-size 12G

其中 vfs-cache-mode 可选参数为 off|minimal|writes|full,默认为 off,写入文件时无法随机寻址,因此无法用于 aria2、Transmission 等分块下载软件。writesfull 则可以很好地模拟本地文件系统,writes 模式下只读打开的文件无缓存,full 模式下读写均有缓存。

vfs-cache-max-age 设置缓存保存时间,vfs-cache-max-size 设置缓存大小。

有一个很重要的参数 --allow-other,表示允许其他用户访问挂载的目录,否则默认其他用户无法访问,不注意的话根本无从排查。而这个参数要求配置 fuse,将 /etc/fuse.conf 中的 user_allow_other 取消注释。--allow-root 参数允许 root 用户访问,同样需要设置 user_allow_other

参数 -vv 可查看 log 以排查错误,--daemon 以守护进程运行等。更多可参考:https://rclone.org/commands/rclone_mount/

查看一下是否已经挂载:

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
onedrive:       5.0T   18G  5.0T   1% /mnt/onedrive

开机自启

systemd 脚本:

$ cat /etc/systemd/system/rclone.service
[Unit]
Description=Rclone Service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=username
ExecStart=/usr/bin/rclone mount onedrive:/ /mnt/onedrive --vfs-cache-mode full --vfs-cache-max-age 24h --vfs-cache-max-size 12G
ExecStopPost=/bin/fusermount -qzu /mnt/onedrive

[Install]
WantedBy=multi-user.target

其中 User 设置为所运行的用户。

我实际使用时,停止进程后无法自动取消挂载,文件夹异常,因此用 fusermount -qzu /mnt/onedrive 取消挂载。

另外,开机时 Transmission 可能会在 Rclone 之前运行,此时目录未挂载,Transmission 就会出错,于是修改其 systemd 脚本:

$ vim /lib/systemd/system/transmission-daemon.service

After=network.target 修改为 After=network.target rclone.service,这样 Transmission 就在 Rclone 后启动。

Linux

本作品根据 署名-非商业性使用-相同方式共享 4.0 国际许可 进行授权。

适配器模式 Adapter Pattern

生成器模式 Builder Pattern