睡眠不足之下的Tavern文件双端同步尝试

为什么睡眠不足呢呃是因为这里

因为有电脑和手机同步消息记录和配置文件信息的需求,所以打算尝试着搞一个能够手机电脑同步的东西。查了查资料,首先选定了Syncthing。

当时啊,我以为,这东西大概花个一个小时就能弄好,我错了。我发现这比东西是真的难用。

Syncthing's Conflict Hell

配置好Syncthing之后,尝试同步。我当时忘记截图了,不放图了,这是Wikipedia的。虽然是Mac端但是界面大差不差(为什么这么糊)

依稀可以看到左边的Folders代表要同步的文件夹,右边的Remote Devices代表的是要连接的设备。好了,手机电脑都配置好Syncthing(手机使用的是Syncthing-Fork,downloaded from F-Droid)。

第一个问题:文件访问权限。

我的手机系统是EvolutionX 10.3(rooted),Android版本15。这个版本,谷歌似乎又加强了什么所谓的文件安全性,所以部署在Termux里面的SillyTavern,理论上来讲当然是在系统文件管理里面看不到,所以选择了方法:绑定挂载,mount --bind


Linux 中的绑定挂载(bind mount)是指将一个已挂载的文件系统或目录,再挂载到另一个挂载点,使得两个挂载点指向同一个文件系统或目录,实现数据共享和跨文件系统访问的功能。

绑定挂载的原理:

绑定挂载实际上是将一个目录或文件的inode信息,复制到另一个目录的dentry(目录项)中,使得两个目录项指向同一个inode,也就是指向同一个文件或目录的数据块。这意味着对其中一个目录的修改,会立即反映到另一个目录。

绑定挂载的用法:

绑定挂载使用 mount --bind 命令。

mount --bind <源目录> <目标目录>

例如:

mkdir /mnt/source
mkdir /mnt/target
mount --bind /mnt/source /mnt/target

这几条命令会将 /mnt/source 目录绑定挂载到 /mnt/target 目录。现在,对 /mnt/source 或 /mnt/target 的任何修改,都会在另一个目录中体现出来。

绑定挂载和符号链接的区别在于,符号链接(ln -s )只是一个指向目标的快捷方式或指针。很多程序(尤其是某些老旧的或者安全要求高的程序,比如在 chroot 环境下)可能无法正确处理符号链接。

绑定挂载则是从文件系统的层面创建了一个“镜像”或“传送门”。对于系统上运行的所有程序来说,挂载点的目录就是一个真实的、存在的目录,它们完全感知不到这其实是另一个地方的内容。

虽然绑定挂载可以实现类似Docker 卷的功能,但绑定挂载依赖于主机的文件系统,而Docker 卷是在Docker 内部管理,具有更好的隔离性和可移植性。此处不再赘述。


所以先选用绑定挂载,因为不清楚SillyTavern内部在Linux环境下引用文件的原理,试试。

首先创建了一个开机自启的文件:bind_termux.sh:

#!/system/bin/sh

# 等待系统准备好,以防万一
sleep 15

# 定义源路径和目标路径
SOURCE_PATH="/data/data/com.termux/files/home/SillyTavern/data"
TARGET_PATH="/storage/emulated/0/Termux-Sync-Mount"

# 执行绑定挂载
mount -o bind "$SOURCE_PATH" "$TARGET_PATH"

然后把这个脚本放到Magisk目录:/data/adb/service.d ,设置该脚本的权限为755(rwxr-xr-x,即所有的执行都被勾选)然后重启手机。

但是这里,重启了之后,脚本并没有生效。排查了半天之后,觉得文件管理器可能有文件查看权限问题,所以在Termux终端内输入:

su
mount -o bind "/data/data/com.termux/files/home/SillyTavern/data" "/storage/emulated/0/Termux-Sync-Mount"

然而终端返回了一个错误:

mount: bad /etc/fstab: No such file or dictionary

这个错误提示mount命令因为某种原因(很可能是安卓15的新特性)没能正确解析我的参数,于是 fallback 到了去查找一个安卓系统上根本不存在的配置文件,导致报错。换用了更现代的mount --bind之后,问题依旧。这些问题都指向了背后肯定有更深层的原因。所以在Termux内:

ls -Z -d /data/data/com.termux/files/home/SillyTavern/data
ls -Z -d /storage/emulated/0/Termux-Sync-Mount

输出结果:

u:object_r:app_data_file_s0:c153,c258,c512,c768 /data/data/com.termux/files/home/SillyTavern/data
u:object_r:app_data_file_s0:c153,c258,c512,c768 /storage/emulated/0/ST-DataSync

初次认定,可能是文件夹权限创建出了问题,这里ST-DataSync居然和根目录的权限一样,是 app_data_file_s0 ,而我查看了另外一个Music文件夹,权限是fuse。怀疑MT管理器可能错误地将自己的SELinux上下文赋予了这个新创建的文件夹。所以再次尝试纠正:

restorecon -vR /storage/emulated/0/ST-DataSync
ls -Z -d /storage/emulated/0/ST-DataSync
mount --bind /data/data/com.termux/files/home/SillyTavern/data /storage/emulated/0/ST-DataSync

重启之后,文件夹权限的确变成了media_rw,但奇葩的事情是,Termux内输入: ls /storage/emulated/0/ST-DataSync ,文件的确全显示出来了,然而无论我用MT管理器还是MiXplorer看,仍然是空。当时就严重怀疑这是挂载命名空间隔离的锅。所以折腾了半天,算了。改用另外一种方法,符号链接。把data文件夹单独挪到外面,然后在Termux内创建一个名为data的符号链接,问题顺理成章地解决。

第二个问题:冲突地狱

在电脑端也配置好了符号链接之后,要开始做数据同步了。Syncthing内一切完备之后,开始同步data文件夹。

然后电脑端疯狂报错,七十来个Conflict,手动修了,这个时候我已经有点红温了。再次同步,还有。我急了。

情况是,电脑端原本有一个很久没玩的SillyTavern,然后手机端有另一个最新的SillyTavern。而我手机和电脑的Syncthing文件夹配置都是:发送和接收。一旦遇到有类似的、相同的文件,它就不知道如何是好,因为它不读取文件内容,只是单纯地同步文件,一旦遇到这种情况,就不知如何是好了,然后把所有的冲突文件都交给用户自己解决,而它的冲突文件命名规则又正好又臭又长,belike:

而SillyTavern的data恰巧微小文件变化极多、文件内容变动极其复杂。所以Syncthing对于同步音乐文件夹没什么问题,但是一旦涉及到这种,就显得有些力不从心。(虽然同步音乐文件夹也是一坨屎因为它很多时候连不上,而且手机端的Syncthing-Fokr根本没有解决冲突文件的入口)。

搞了半天Syncthing约等于白搞,所以后来换了代码界最可靠的方案:Git。账号命名令牌之类的小问题,在Git官方FAQ都能找到,就不再一一赘述。虽然麻烦了点,每次换端游玩的时候得手动:

git add . # 添加所有有变动的文件
git commit -m "update" # 提交到上传区,并且备注"update"
git push # 推送到github

然后另一个端:

git pull

但是总比花几百年解决恼人的同步问题要好得多。

至于音乐文件夹同步?我选择了MiXplorer的FTP服务器。手动操作,GUI拖拽,但是比ADB方便的多。Syncthing是啥,真不熟.jpg。等日后完善吧,现在的真的不大行。应用场景有点太窄了。


睡眠不足之下的Tavern文件双端同步尝试
http://localhost:50392/archives/shui-mian-bu-zu-zhi-xia-de-tavernwen-jian-shuang-duan-tong-bu-chang-shi
作者
Cynsm
发布于
2025年08月01日
许可协议