前阵子帮人调一台群晖,他用 rclone 把网盘挂到本地当电影库,播放器一扫就报错,日志里全是 input/output error。查了半天不是网络问题,是挂载参数里 --vfs-cache-mode 没设。这个参数不设就是 off,很多人照抄一条命令就上车,后面所有奇怪的问题都从这里来。
这篇把我这几台机器上一直在用的四档配置和几个配套参数写清楚,省得你一个个试。
vfs cache 到底在缓存什么
rclone mount 本质是把网盘的 HTTP 接口伪造成一个本地文件系统。网盘接口只支持「整块上传、整块下载」,不支持在文件中间随机改几个字节。而本地文件系统是按「打开、seek、读一点、写一点、关闭」来用的,两者语义对不上,中间那层就是 VFS cache。
所以 --vfs-cache-mode 决定的是:这些对不上的操作,在本地先落到磁盘上缓冲,还是直接拒绝。
缓冲目录默认在 ~/.cache/rclone/vfs,可以用 --cache-dir 挪到大盘上。这一层不理解清楚,后面选档位全是猜。
off:默认值,只能顺序读
off 就是完全不缓冲。读的时候就着 HTTP 流往下读,写的时候必须一次写完并且能直接上传。
它能干的事:播放器顺序播放一个 mp4、cp 一个大文件、rsync 单向推上去。
它不能干的事:任何需要回退读写的操作——播放器拖进度条、用 mkvtoolnix 改字幕、Photoshop 存盘、甚至 vim 保存都会失败。报错通常是 input/output error 或者 failed to open with O_WRONLY。
如果你只是拿它当个只读的媒体库,off 其实是最省资源的,内存和磁盘都不占。
minimal:给流媒体准备的
minimal 只缓存「正在被读」的文件,而且只缓存读到的那一段,读完就丢。它解决的是播放器 seek 的问题——拖进度条时不用重新从网盘拉整个文件头。
限制还在写这一侧:写仍然要求你能一次写完并直接上传成功。所以我一般不推荐卡在 minimal,除非你机器内存特别紧张。
writes:写先落地,读还是直连
writes 会把你写的文件先写到本地缓存目录,等上传成功再标记完成。中途断电、断网,文件还在缓存里,下一次挂载会重试上传。
这一档适合「NAS 上偶尔往里丢东西」的场景:WebDAV 上传、下载器完成后自动搬进去、手机备份同步。播放器那侧还是直连读,拖进度条有时会卡一下但能用。
要注意 --vfs-write-back 这个参数,默认 5 秒。意思是关闭文件后等 5 秒才真正开始上传。下载器把文件挪进去立刻改名或者挪走,容易撞上「文件还没传完」的报错,这种场景我一般调到 30 秒。
full:读写都走本地,最像本地盘
full 是唯一能安心跑随机写的一档。所有打开的文件先复制到缓存目录,读写都在本地做,关闭之后整份上传回去。
代价很直接:你的缓存盘得装得下同时打开的文件。剪一个 4K 片子,缓存目录里就会多一份同样大小的临时文件。
这一档适合:直接用 NAS 上的软件编辑网盘里的文档、给视频改字幕、跑一些会写临时文件的工具。
按你干什么选,别按别人推荐选
- 纯媒体库,只读不写 → off 或 minimal
- 下载器落盘、手机备份、偶尔上传 → writes
- 要在网盘目录里直接改文件、跑编辑类软件 → full
- 一个挂载点既要播放又要改东西 → 直接 full,别省那点缓存
我自己的主力机是 full + 200G 缓存上限,另一台纯做播放的盒子是 off,用了两年没出过事。
四个必须一起设的参数
光改 mode 不改这几个,还是会出问题:
--vfs-cache-max-size 200G # 缓存上限,超了按 LRU 删
--vfs-cache-max-age 24h # 多久没动就清掉
--dir-cache-time 1h # 目录列表缓存时间,调大能省很多请求
--umask 002 # 让同组用户也能读写
--allow-other # 不加的话只有挂载用户能看见
--allow-other 这个坑最常见。你用 root 挂上去,然后 Plex 用 plex 用户跑,结果目录里空空如也,不是挂载失败,是 FUSE 默认不允许别的用户访问。群晖上还要在 /etc/fuse.conf 里放开 user_allow_other。
--umask 不设的话,从别处写进来的文件权限可能是 600,同组用户照样读不了。
两个我实打实踩过的报错
第一个:Failed to copy: vfs cache: failed to upload
下载器把文件写进挂载点,写完立刻改名成 .mkv,结果上传的还是一个临时文件名,改名后源文件不存在,上传就失败。解决是让下载器写到本地盘,完成后再 mv 进挂载点,或者把 --vfs-write-back 调大。
第二个:Transport endpoint is not connected
这个基本是挂载进程没了,但目录还挂在那。fusermount -u /mnt/xxx 解掉再重挂就行。如果反复出现,去看 journalctl -u 你的服务名,多半是 token 过期或者网盘限流。
顺带一句,网盘那边有单日流量和并发限制,不要用 --transfers 32 这种参数去怼,被限流之后所有操作都会变慢,看起来像挂载坏了。
开机自动挂载,别写 rc.local
rc.local 在系统起来的时候网络还没通,挂载必然失败。用 systemd:
[Unit]
Description=rclone mount
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/rclone mount remote: /mnt/pan \
--config /root/.config/rclone/rclone.conf \
--vfs-cache-mode full \
--vfs-cache-max-size 200G \
--allow-other --umask 002
ExecStop=/bin/fusermount -u /mnt/pan
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Type=notify 很重要,rclone 支持 systemd 通知,这样 systemctl status 能看到真实的挂载状态,而不是一个启动就退出的壳。
如果是 Docker 里跑,记得给容器 /dev/fuse 和 SYS_ADMIN,不然挂载会直接报 fusermount: failed to open /dev/fuse。
你们现在挂载用的是哪一档?有没有碰到过拖进度条就卡死的情况,说说看是什么网盘。