本文完整阅读约需 32 分钟,如时间较长请考虑收藏后慢慢阅读~

作为一款性能优异、功能全面的文件存储系统,Seafile提供了全平台的客户端供用户使用,但如果需要将Seafile与其他系统集成,我们就需要使用如WebDAV这样的开放协议将Seafile的存储功能以WebDAV的接口暴露出来。然而,自从7.1版本之后,按照Seafile官方文档对其进行配置会出现Seafile无法监听WebDAV端口的问题。本文将为读者介绍这一问题的解决方法。

0x01 发现问题

首先介绍一下笔者的Seafile环境:

  • 最初安装版本:6.x
  • 陆续升级到最新版本:8.0.5
  • 此前未配置过WebDAV

由于笔者最近在做的一个小项目需要利用到Seafile的存储能力,但并不希望接入seafhttp,而是想要利用现有的WebDAV库对其进行读写,因此按照官方文档配置了seafdav.conf,配置文件如下所示:

[WEBDAV]

# Default is false. Change it to true to enable SeafDAV server.
enabled = true

port = 8080

# If you deploy seafdav behind nginx/apache, you need to modify "share_name".
share_name = /seafdav

保存配置文件后,笔者执行了systemctl restart seafile对Seafile进行了重启操作,却发现无法连通8080端口,执行netstat -nlp | grep 8080后发现该端口根本没有被监听:

0x02 分析问题

首先,笔者尝试通过./seafile.sh restart重启Seafile,观察是否有报错输出,结果如下:

可以发现,在重启的过程中并没有出现报错,说明问题可能出在其他的地方。

接下来,笔者尝试查看日志。Seafile的目录下存在以下几类日志:

  • /logs/ccnet.log: Seafile的RPC服务日志
  • /logs/seafile.log: Seafile文件服务器日志
  • /logs/controller.log: Seafile服务端子进程控制器日志
  • /logs/seahub.log: Seahub日志

既然官方文档中要求重启的是Seafile服务,那么可以基本排除seahub.log的嫌疑,接下来要做的就是对另外三个日志进行阅读。笔者分别对这三个日志执行了tail -f -n 100命令,得到结果分别如下:

  • /logs/ccnet.log:
[02/20/21 00:21:18] start to serve on pipe client
[02/20/21 00:26:19] start to serve on pipe client
[02/20/21 00:28:06] start to serve on pipe client
[02/20/21 00:30:44] start to serve on pipe client
[02/20/21 00:31:17] start to serve on pipe client
...
  • /logs/seafile.log:
2021-05-23 11:51:33 ../common/seaf-utils.c(333): Use database Mysql
2021-05-23 11:51:33 http-server.c(192): fileserver: worker_threads = 20
2021-05-23 11:51:33 http-server.c(207): fileserver: fixed_block_size = 4194304
2021-05-23 11:51:33 http-server.c(222): fileserver: web_token_expire_time = 7200
2021-05-23 11:51:33 http-server.c(237): fileserver: max_indexing_threads = 10
2021-05-23 11:51:33 http-server.c(252): fileserver: max_index_processing_threads= 3
2021-05-23 11:51:33 http-server.c(274): fileserver: cluster_shared_temp_file_mode = 600
2021-05-23 11:52:35 start to serve on pipe client
2021-05-23 11:55:40 start to serve on pipe client
...
  • /logs/controller.log:
2021-05-23 11:59:13 seafile-controller.c(416): pid file /home/seafile/pids/seafdav.pid does not exist
2021-05-23 11:59:13 seafile-controller.c(443): seafdav need restart...
2021-05-23 11:59:13 seafile-controller.c(81): spawn_process: /bin/python3 -m wsgidav.server.server_cli --server gunicorn --root / --log-file /home/seafile/logs/seafdav.log --pid /home/seafile/pids/seafdav.pid --port 8080 --host 0.0.0.0
2021-05-23 11:59:13 seafile-controller.c(115): spawned /bin/python3, pid 8621
2021-05-23 11:59:14 seafile-controller.c(123): Traceback (most recent call last):
  File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/server/server_cli.py", line 39, in <module>
    from wsgidav.default_conf import DEFAULT_CONFIG, DEFAULT_VERBOSE
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/default_conf.py", line 18, in <module>
    from wsgidav.dir_browser import WsgiDavDirBrowser
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/dir_browser/__init__.py", line 2, in <module>
    from ._dir_browser import WsgiDavDirBrowser
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/dir_browser/_dir_browser.py", line 9, in <module>
    from jinja2 import Environment, FileSystemLoader
ModuleNotFoundError: No module named 'jinja2'
...

可以看出,controller.log中存在与WebDAV相关的报错,说明的确在启动WebDAV服务的时候出现了错误。

0x03 解决问题

阅读错误日志,我们会发现似乎是缺少了jinja2wsgidav两个Python包。于是笔者执行了如下命令安装之,并在安装结束后重启Seafile服务:

pip3 install wsgidav jinja2
systemctl restart seafile

重启Seafile服务后,笔者发现依旧没有任何进程在监听8080端口,于是再次查看controller.log日志:

2021-05-23 12:02:52 seafile-controller.c(416): pid file /home/seafile/pids/seafdav.pid does not exist
2021-05-23 12:02:52 seafile-controller.c(443): seafdav need restart...
2021-05-23 12:02:52 seafile-controller.c(81): spawn_process: /usr/bin/python3 -m wsgidav.server.server_cli --server gunicorn --root / --log-file /home/seafile/logs/seafdav.log --pid /home/seafile/pids/seafdav.pid --port 8080 --host 0.0.0.0
2021-05-23 12:02:52 seafile-controller.c(115): spawned /usr/bin/python3, pid 9237
2021-05-23 12:02:53 seafile-controller.c(123): Traceback (most recent call last):
  File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/server/server_cli.py", line 43, in <module>
    from wsgidav.dc.domain_controller import SeafileDomainController
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/dc/domain_controller.py", line 7, in <module>
    from wsgidav.dc import seahub_db
  File "/home/seafile/seafile-server-8.0.5/seahub/thirdpart/wsgidav/dc/seahub_db.py", line 3, in <module>
    from sqlalchemy import create_engine
ModuleNotFoundError: No module named 'sqlalchemy'

从错误日志中可以看出,WebDAV模块依旧在报错,而报错的内容为缺少sqlalchemy包,于是继续安装之:

pip3 install sqlalchemy
systemctl restart seafile

重启Seafile服务后,再执行netstat -nlp可以发现端口已经被成功监听,在本地对8080端口进行curl也能正常返回结果:

0x04 问题根源

通过上文解决问题的过程,我们会发现问题并不出在配置文件上,而是缺失了WebDAV服务所依赖的库。在Seafile官方手册中搜索jinja2,笔者发现了一篇升级指南

From 7.1.0 version, Seafile will depend on the Python 3 and is not compatible with Python 2.

Therefore you cannot upgrade directly from Seafile 6.x.x to 7.1.x.

If your current version of Seafile is not 7.0.x, you must first download the 7.0.x installation package and upgrade to 7.0.x before performing the subsequent operations.

To support both Python 3.6 and 3.7, we no longer bundle python libraries with Seafile package. You need to install most of the libraries by your own as bellow.

从指南中可以看出,Seafile在7.1.0版本发布之后,为了同时兼容Python3.6和3.7,不再将依赖库打包在Seafile内部,而是直接引用系统的依赖库,因此在升级到7.1.0版本后,用户需要手动安装对应的依赖库。该升级指南同样提供了需要手动安装的依赖库列表,如下所示:

pip3 install --timeout=3600 Pillow pylibmc captcha jinja2 sqlalchemy==1.3.8 \
    django-pylibmc django-simple-captcha python3-ldap

因此如果要让升级到7.1.0版本后的Seafile正常运行,除了上文所提到了jinja2wsgidavsqlalchemy包外,还需要根据这里的升级指南安装其他依赖。安装完成后再次重启Seafile服务,则不会有其他问题。

笔者回忆了一下升级Seafile的过程,并未出现任何关于上文所述的提示,查看7.0到7.1版本的升级脚本:haiwen/seafile-server/blob/master/scripts/upgrade/upgrade_7.0_7.1.shgrade_7.0_7.1.sh,同样没有看到相关提示,这说明Seafile开发组在处理这一版本变化时,并未尽到告知用户的责任,只是在文档中进行说明,却并没有在升级的时候提示用户。而当笔者搜索上文controller.log中报错时,发现社区中有大量用户曾反应过此问题:

[SOLVED] 7.0.5 CE to 7.1.2 CE Upgrade Gives WebDAV 502 Error

[SOLVED] Seafdav 502 Bad Gateway after upgrade to 7.1.3 yesterday (Docker)

Seafdav does not work (seafdav.pid problem)

在社区中搜索WebDAV 502能看到大量的相关用户反馈,而官方对其态度却极为冷淡,几乎不回复这些反馈,seafile-serverGitHub仓库也拒绝接受Issue反馈。

这样冷淡的态度不仅体现在对用户反馈的无视,也体现在对第三方开发者的冷淡上,举个例子,macOS Mojave的发布带来了夜间模式,但Seafile客户端的Icon却没有支持之,导致了暗色的菜单栏上出现了暗色的Icon,极为不美观,如果没有Bartender这类软件能帮助用户隐藏Icon,否则Seafile客户端丑陋的Icon真是想让用户有卸载Seafile的冲动(Seadrive同理):

但实际上在Mojave发布的2018年,就有热心的用户提出了解决方案:Use template images for mac menu bar icon #1140,该解决方案利用了UIKit的Template Image能力,实现了图标颜色的自适应,笔者在本地测试了他的修改,发现效果非常完美,但遗憾的是官方在过去的两年半内既没有解决此问题,也没有合入此PR,甚至连一条回复都没能给出。截止本文撰写的日期(2021年5月23日),这一存在了接近三年的问题依旧未被官方给出任何方案进行解决。

作为一款标榜『开放源代码』的项目,这样的态度真的是在认真做开源吗?笔者不禁对此表示怀疑,而相信读到这里的读者也有了自己的判断,无需笔者多言。


附注:本文所提到的问题只会在升级后的Seafile版本中出现,如果是全新安装的Seafile,则不会出现此问题,希望这篇文章能为遇到类似问题的读者提供解决的思路。