Seafile同步问题分析与解决

来自个人维基
Hovercool留言 | 贡献2026年6月16日 (二) 09:24的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳转到导航 跳转到搜索

Seafile 同步问题分析与解决

日期:2026-06-09 服务器:Ubuntu 24.04 服务端:自建 Seafile 服务器


一、问题现象

SeaDrive FUSE 挂载盘文件不同步:

  • 服务端已删除的文件在挂载盘上仍然显示
  • 服务端 head_commit_id 与本地 master 不一致
  • 进程只有 3 个线程(2 FUSE + 1 主线程),没有同步工作线程
  • seadrive 反复重启(每几秒一次),日志中不断出现 Starting SeaDrive clientrpc server started

二、排查过程(详细)

2.1 第一轮:查看运行状态和日志

操作:

systemctl status seadrive
ps aux | grep seadrive
tail -f /home/openclaw/.seadrive/log

发现:

  • seadrive 进程在运行,但日志中有大量 SSL 错误
  • 进程反复重启,systemd Restart=on-failure 导致 crash-loop
  • 日志显示 seadrive 在启动后立即退出,systemd 10 秒后重新拉起

2.2 SSL 证书问题

日志报错:

http-tx-mgr.c(557): libcurl failed to GET https://<server>/api2/repos/:
  Problem with the SSL CA cert (path? access rights?).

排查过程:

  1. 用系统 curl 测试 curl https://<server>/api2/ping/ → ✅ 正常
  2. 检查 seadrive 进程的环境变量 → SEAFILE_SSL_CA_PATH 未设置
  3. 查看 seadrive 源码中 load_ca_bundle() 函数 → 读取 SEAFILE_SSL_CA_PATH 环境变量
  4. 检查 AppImage 打包的 libcurl → 链接了自带的 OpenSSL 1.1,不是系统 OpenSSL 3.0

解决: 在 systemd service 中添加:

Environment="SEAFILE_SSL_CA_PATH=/etc/ssl/certs/ca-certificates.crt"

验证: 重启后 SSL 错误消失(日志中不再出现),且通过 /proc/<pid>/fd/ 确认 seadrive 打开了 CA 证书文件。

2.3 同步不工作 — 深入分析

SSL 问题解决后,seadrive 不再报错,但文件仍然不同步。

排查步骤:

步骤 1:检查进程线程数

ps -T -p <seadrive_pid>

→ 只有 3 个线程(2 FUSE + 1 主线程),没有 glib 线程池工作线程

步骤 2:检查网络连接

ls -la /proc/<pid>/fd/ | grep socket
ss -tnp | grep seadrive

→ 只有本地监听 socket(RPC server),没有 TCP 连接到 seafile 服务器

说明 sync-mgr 根本没有发起 HTTP 请求。

步骤 3:查看 seadrive 源码中 sync-mgr 的启动路径

下载 seadrive-fuse 源码,追踪调用链:

seadrive.c (main 函数):

// 在子线程中运行 seafile 会话
pthread_create(&tid, &attr, seafile_session_thread, NULL);

seafile-session.c:

void seafile_session_start(SeafileSession *session) {
    on_start_cleanup(session);          // 提交清理 job
    event_base_loop(session->ev_base, 0);  // 进入事件循环
}

关键发现: on_start_cleanup 通过 job manager 提交一个清理任务,任务完成后回调 cleanup_job_done,而 seaf_sync_manager_start() 正是在 cleanup_job_done 里被调用的!

static void cleanup_job_done(void *vdata) {
    http_tx_manager_start(session->http_tx_mgr);
    seaf_sync_manager_start(session->sync_mgr);  // ← 同步定时器在这里启动
    seaf_repo_manager_start(session->repo_mgr);
    // ...
}

步骤 4:查看 job 提交机制

job-mgr.c:

SeafJobManager *seaf_job_manager_new(SeafileSession *session, int max_threads) {
    mgr->thread_pool = g_thread_pool_new(job_thread_wrapper, NULL,
                                          max_threads, FALSE, NULL);
    // 第5个参数传 NULL!不检查错误!
    return mgr;
}

int job_thread_create(SeafJob *job) {
    g_thread_pool_push(job->manager->thread_pool, job, NULL);
    // 如果 thread_pool 是 NULL,push 静默失败
    event_base_once(session->ev_base, job->pipefd[0], EV_READ, job_done_cb, job, NULL);
    return 0;
}

根因确认: g_thread_pool_new 返回 NULL → thread_pool 为 NULL → g_thread_pool_push 静默失败 → 清理 job 不执行 → cleanup_job_done 不调用 → sync-mgr 定时器不启动。

步骤 5:验证 GLib 版本

用 Python ctypes 测试 AppImage 自带的 GLib:

glib = ctypes.CDLL("/tmp/squashfs-root/usr/lib/libglib-2.0.so.0")
glib_major_version.value  # → 2
glib_minor_version.value  # → 66
glib_micro_version.value  # → 8

AppImage 打包的 GLib 版本:2.66.8(2020年发布) 系统 GLib 版本:2.80.0(Ubuntu 24.04 自带)

2.4 两个 seadrive 进程之谜

现象: 每次启动 seadrive 都会产生两个进程:

/usr/local/bin/seadrive ...          # wrapper 进程
/tmp/.mount_seadriXXXXX/usr/bin/seadrive ...  # 真正的 seadrive

原因: AppImage 的运行机制。

  1. 执行 AppImage 文件
  2. AppImage runtime 自动将自身挂载到 /tmp/.mount_seadriXXXXX/(只读 FUSE 挂载)
  3. 从挂载点执行真正的二进制
  4. wrapper 进程监控子进程状态

验证: pkill 杀掉子进程后,wrapper 检测到子进程退出,自动重新拉起,产生新的挂载点。

2.5 LD_PRELOAD 方案尝试

尝试用系统 GLib 覆盖 AppImage 自带的旧版:

Environment="LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0"

结果: LD_PRELOAD 生效(/proc/pid/maps 确认加载了系统 GLib),但线程数仍然为 3。说明问题不仅是 GLib 版本,可能和 AppImage 的挂载环境、libcurl/OpenSSL 的初始化路径也有关系。

2.6 多版本兼容性测试

从 GitHub Releases 和 seafile 官方下载站下载了多个版本逐一测试:

版本 类型 大小 守护进程版本 GLib 线程数 结果
v3.0.12 GUI AppImage 161MB 2.0.16 2.66.8 3 ❌ 启动失败
v3.0.12 CLI AppImage 13MB 2.0.16 2.66.8 3 ❌ 同步不工作
v3.0.17 CLI AppImage 13MB 3.0.17 2.66.8 3 ❌ 同步不工作
v3.0.21 CLI AppImage 13MB 3.0.21 2.66.8 3 ❌ 同步不工作
v3.0.22 GUI AppImage 154MB 3.0.22 2.66.8 3 ❌ 同步不工作
v3.0.22 CLI AppImage 13MB 3.0.22 2.66.8 ❌ core dump
v3.0.23 CLI 未下载 2.66.8(预计) 未测试(预期一致)

测试方法: 每个版本替换 seadrive 二进制,启动后等待 35 秒(sync-mgr 的 repo list 更新间隔),检查线程数和日志。

结论: 所有 AppImage 版本都用 Ubuntu 20.04 构建环境 + GLib 2.66.8,线程池问题普遍存在。

2.7 关于某次手动启动正常的原因

之前文档提到某次手动启动(非 systemd)同步正常。分析可能原因:

  • 手动启动时的环境变量(PATH、LD_LIBRARY_PATH 等)与 systemd 不同
  • 手动启动时终端会话的 cgroup/资源限制不同
  • 但后续无法复现,且所有 AppImage 版本在 systemd 下都有问题

三、最终方案:seafile-daemon + seafile-cli

3.1 seadrive vs seafile-daemon 详细对比

对比维度 seadrive (AppImage) seafile-daemon (apt)
本质 FUSE 虚拟挂载盘 传统文件同步客户端
工作方式 按需拉取,文件在访问时才下载 全量同步到本地目录
本地占用 小(仅缓存访问过的文件) 大(所有文件完整副本)
离线可用 仅缓存过的文件 所有已同步文件
双向同步
安装方式 手动下载 AppImage apt install
依赖管理 自包含(打包了 GLib/OpenSSL/curl 等) 系统包管理
GLib 版本 2.66.8(2020年,自带的) 2.80.0(系统)
OpenSSL 1.1(自带的) 3.0(系统)
线程池 ❌ 不工作 ✅ 正常(7+ 线程)
稳定性 ❌ crash-loop ✅ 稳定
二进制大小 13MB(CLI)~ 161MB(GUI) 404KB(daemon)
进程模型 wrapper + 子进程(2个) 单进程
适用场景 节省磁盘空间、按需访问 全量同步、离线可用

3.2 安装与配置步骤

# 1. 安装系统包
sudo apt-get install -y seafile-daemon seafile-cli

# 2. 初始化数据目录
mkdir -p /home/<user>/.seafile-data
echo "/home/<user>/.seafile-data" > /home/<user>/.ccnet/seafile.ini

# 3. 启动守护进程
seaf-cli start

# 4. 查看远程仓库列表
seaf-cli list-remote -s https://<server> \
  -u <username> \
  -T <token>

# 5. 同步指定仓库到本地
seaf-cli sync -l <library_id> \
  -s https://<server> \
  -u <username> \
  -T <token> \
  -d /home/<user>/SeaFile

# 6. 查看同步状态
seaf-cli status

3.3 开机自启配置

sudo tee /etc/systemd/system/seafile-daemon.service << 'EOF'
[Unit]
Description=Seafile daemon
After=network.target

[Service]
Type=forking
Environment="HOME=/home/<user>"
ExecStart=/usr/bin/seaf-cli start
ExecStop=/usr/bin/seaf-cli stop
User=<user>
Group=<user>
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable seafile-daemon
sudo systemctl start seafile-daemon

3.4 验证

# 检查进程和线程数(正常应有 7+ 线程)
ps -T -p $(pgrep seaf-daemon)

# 检查同步状态
seaf-cli status

# 如果上述命令出错,先启动
$ seaf-cli start

# 检查同步目录
ls -la /home/<user>/SeaFile/

四、关键文件路径

用途 路径
seafile 数据目录 ~/.seafile-data/
seafile 配置目录 ~/.ccnet/
seafile 日志目录 ~/.ccnet/logs/
同步目录 ~/SeaFile/
seafile-daemon systemd service /etc/systemd/system/seafile-daemon.service
seadrive 二进制(保留备用) /usr/local/bin/seadrive
seadrive 旧 service(已 disable) /etc/systemd/system/seadrive.service
seadrive 配置 ~/.seadrive/seadrive.conf
seadrive 日志 ~/.seadrive/log
seadrive 数据 ~/.seadrive/data/
seadrive-fuse 源码 /tmp/seadrive-fuse/

五、后续注意事项

  1. seadrive 新版可试:如果官方发布新版 AppImage(用更新的 GLib 构建),可以随时切回去测试

    sudo systemctl stop seafile-daemon
    sudo systemctl enable seadrive
    sudo systemctl start seadrive
  2. AppImage 残留清理:每次 seadrive 启动会在 /tmp/.mount_seadri*/ 创建 FUSE 挂载点,crash 后会残留

    sudo umount -l /tmp/.mount_seadri* 2>/dev/null
  3. seafile-daemon 日志~/.ccnet/logs/

  4. token 管理:seafile token 长期有效,更换时需要重新获取

  5. 切换回 seadrive 测试

    sudo systemctl stop seafile-daemon
    sudo systemctl disable seafile-daemon
    sudo systemctl enable seadrive
    sudo systemctl start seadrive

    恢复 seafile-daemon:

    sudo systemctl stop seadrive
    sudo systemctl disable seadrive
    sudo systemctl enable seafile-daemon
    sudo systemctl start seafile-daemon