升级步骤

本页面说明将 Fess 从旧版本升级到最新版的步骤。

Warning

升级前的重要注意事项

  • 升级前必须获取备份

  • 强烈建议在测试环境提前验证升级

  • 升级期间服务会停止,请设置适当的维护时间

  • 根据版本不同,配置文件的格式可能已更改

支持版本

本升级步骤支持以下版本之间的升级:

  • Fess 14.x → Fess 15.9

  • Fess 15.x → Fess 15.9

Important

Fess 14.x 对应 OpenSearch 2.x 系列,Fess 15.9 对应 OpenSearch 3.8.0。 由于 Fess 专用的 OpenSearch 插件必须与 OpenSearch 版本完全一致, 因此从 14.x 升级时,也必须同时对 OpenSearch 进行主版本升级。 请参阅 步骤 4: 升级 OpenSearch

Note

如果从更旧的版本(13.x 及更早)升级,可能需要逐步升级。 详情请确认发布说明。

升级前的准备

确认版本兼容性

请确认升级目标版本与当前版本的兼容性。

计划停机时间

升级工作需要停止系统。请考虑以下因素计划停机时间:

  • 备份时间: 10分钟 ~ 数小时(取决于数据量)

  • 升级时间: 10 ~ 30分钟

  • 运行确认时间: 30分钟 ~ 1小时

  • 预留时间: 30分钟

推荐维护时间: 总计 2 ~ 4小时

步骤 1: 数据备份

升级前,请备份所有数据。

备份配置数据

  1. 从管理页面备份

    登录管理页面,点击「系统信息」→「备份」。

    备份页面按条目列出以下配置数据。 点击各行下载(不是单个 ZIP 文件,而是按条目分别下载的独立文件。 由于没有批量下载功能,需要将所需项目逐一下载)。

    • fess_basic_config.bulk - 配置索引(爬取设置、调度器、标签、 关键词匹配、角色、Web/文件认证等 19 个索引)

    • fess_config.bulk - 除上述 19 个索引外,还包含爬取信息、失败 URL、作业日志、 缩略图队列等运行时数据,共 25 个索引

    • fess_user.bulk - 用户、角色、群组

    • system.properties - 包含常规设置的系统设置

    • fess.json - 索引设置(分片数、index.knn 等)

    • doc.json - 文档映射(字段定义)

    Note

    fess_config.bulk 包含 fess_basic_config.bulk。作为升级前的 配置备份,fess_basic_config.bulkfess_user.bulksystem.properties 这 3 个文件就已足够。

    Note

    搜索日志、点击日志等日志数据(search_log.ndjsonclick_log.ndjsonfavorite_log.ndjsonuser_info.ndjson)也可从同一页面下载。 如果仅备份配置,则不需要下载这些文件。另外,这些 *.ndjson 文件无法 通过备份页面的上传功能重新导入恢复 (请参阅「回滚步骤」)。

  2. 备份配置文件

    ZIP 版:

    $ cp /path/to/fess/app/WEB-INF/conf/system.properties /backup/
    $ cp /path/to/fess/app/WEB-INF/classes/fess_config.properties /backup/
    $ cp /path/to/fess/bin/fess.in.sh /backup/
    

    RPM 版:

    $ sudo cp /etc/fess/system.properties /backup/
    $ sudo cp /etc/fess/fess_config.properties /backup/
    $ sudo cp /etc/sysconfig/fess /backup/
    

    DEB 版:

    $ sudo cp /etc/fess/system.properties /backup/
    $ sudo cp /etc/fess/fess_config.properties /backup/
    $ sudo cp /etc/default/fess /backup/
    

    Note

    /etc/sysconfig/fess(RPM 版)和 /etc/default/fess(DEB 版)是 用于指定 FESS_PORTFESS_HEAP_SIZESEARCH_ENGINE_HTTP_URLFESS_DICTIONARY_PATH 等内容的环境变量文件。 ZIP 版中与之对应的设置位于 bin/fess.in.sh

  3. 定制的配置文件

    如有定制的配置文件,也请备份:

    $ cp /path/to/fess/app/WEB-INF/classes/log4j2.xml /backup/
    

    Note

    app/WEB-INF/classes/log4j2.xml 是 Fess 本体(Web)进程的日志配置。 爬虫等子进程使用各自独立的文件 (例如 app/WEB-INF/env/crawler/resources/log4j2.xml 等,crawlersuggestthumbnailchunk 共 4 个),如果修改过这些文件, 请一并备份。

备份索引数据

备份 OpenSearch 的索引数据。

方法 1: 使用快照功能(推荐)

使用 OpenSearch 的快照功能备份索引。

Note

要注册文件系统仓库(fs),需要事先在 OpenSearch 的 opensearch.ymlpath.repo 中指定备份目标目录,并重启 OpenSearch。

  1. 配置仓库:

    $ curl -X PUT "http://localhost:9200/_snapshot/fess_backup" -H 'Content-Type: application/json' -d'
    {
      "type": "fs",
      "settings": {
        "location": "/backup/opensearch/snapshots"
      }
    }'
    
  2. 创建快照:

    $ curl -X PUT "http://localhost:9200/_snapshot/fess_backup/snapshot_1?wait_for_completion=true"
    
  3. 确认快照:

    $ curl -X GET "http://localhost:9200/_snapshot/fess_backup/snapshot_1"
    

方法 2: 整体备份目录

停止 OpenSearch 后,备份数据目录。

$ sudo systemctl stop opensearch
$ sudo tar czf /backup/opensearch-data-$(date +%Y%m%d).tar.gz /var/lib/opensearch/data
$ sudo systemctl start opensearch

Docker 版的备份

OpenSearch 的数据保存在 Docker 卷中。compose-opensearch3.yaml 中定义了 用于索引数据的 search01_data 和用于词典文件的 search01_dictionary 共 2 个卷。

Note

实际的卷名会附加 Compose 项目名称(默认为放置 Compose 文件的目录名)作为前缀。 请使用以下命令确认准确的卷名:

$ docker volume ls

停止容器后,备份卷。docker run-v 需要指定 包含前缀的实际卷名:

$ docker compose -f compose.yaml -f compose-opensearch3.yaml stop
$ PROJECT=$(basename "$(pwd)")
$ docker run --rm -v ${PROJECT}_search01_data:/data -v $(pwd):/backup ubuntu tar czf /backup/search01-data-backup.tar.gz /data
$ docker run --rm -v ${PROJECT}_search01_dictionary:/data -v $(pwd):/backup ubuntu tar czf /backup/search01-dictionary-backup.tar.gz /data
$ docker compose -f compose.yaml -f compose-opensearch3.yaml start

Warning

如果在 -v 中指定不带前缀的 search01_data,Docker 不会引用现有卷, 而是会新建一个同名的空卷。命令不会报错,且会生成内容为空的归档文件, 看起来就像是已经完成了备份。

Note

Fess 本体(fess01)的容器没有专用卷,因此备份对象仅为 上述 2 个卷。但是,从管理页面更改的常规设置以及从管理页面安装的 插件仅保存在容器内部,重新创建容器后会丢失。 请通过 Compose 文件的 FESS_JAVA_OPTSFESS_PLUGINS 指定这些内容以实现持久化。

步骤 2: 停止当前版本

停止 Fess 和 OpenSearch。

ZIP 版没有附带用于停止的脚本。bin/fess 如果是使用 -p 选项 启动的,可以使用 PID 文件停止:

$ kill $(cat /path/to/fess/fess.pid)
$ kill <opensearch_pid>

如果启动时未指定 -p,请确认进程 ID 后使用 kill 停止 (仅使用 -d 不会创建 PID 文件)。

RPM/DEB 版 (systemd):

$ sudo systemctl stop fess.service
$ sudo systemctl stop opensearch.service

Docker 版:

$ docker compose -f compose.yaml -f compose-opensearch3.yaml down

步骤 3: 安装新版本

根据安装方法,步骤有所不同。

ZIP 版

  1. 下载并解压新版本:

    $ wget https://github.com/codelibs/fess/releases/download/fess-15.9.0/fess-15.9.0.zip
    $ unzip fess-15.9.0.zip
    

    Note

    Fess 的归档版仅以 ZIP 格式发布(不提供 fess-15.9.0.tar.gz)。

  2. 复制旧版本的配置:

    $ cp /path/to/old-fess/app/WEB-INF/conf/system.properties /path/to/fess-15.9.0/app/WEB-INF/conf/
    $ cp /path/to/old-fess/app/WEB-INF/classes/fess_config.properties /path/to/fess-15.9.0/app/WEB-INF/classes/
    $ cp /path/to/old-fess/bin/fess.in.sh /path/to/fess-15.9.0/bin/
    

    Warning

    如果原样复制 fess_config.propertiesfess.in.sh ,旧版本的值会被沿用,其中也包括 15.9 中默认值已变更的项。例如,升级后新建的作业默认将使用 Groovy。执行最后两条命令之前, 请将各文件与 fess-15.9.0 中的文件进行比较,只迁移自己修改过的值。需要确认的项目请参阅 从 15.8 沿用的配置文件

  3. 如有定制内容,请同时复制以下文件:

    # 日志配置
    $ cp /path/to/old-fess/app/WEB-INF/classes/log4j2.xml /path/to/fess-15.9.0/app/WEB-INF/classes/
    # 已安装的插件
    $ cp -r /path/to/old-fess/app/WEB-INF/plugin/. /path/to/fess-15.9.0/app/WEB-INF/plugin/
    # 主题
    $ cp -r /path/to/old-fess/app/themes/. /path/to/fess-15.9.0/app/themes/
    

    Warning

    在管理页面「页面设计」中编辑过的 JSP(app/WEB-INF/view/),请不要直接复制过去。 如果新版本的 JSP 结构发生了变化,画面可能无法正常显示。 请将修改内容重新应用到新版本的 JSP 上。

    Note

    app/WEB-INF/plugin/ 复制的插件是为旧版本构建的。复制后,请在 fess-15.9.0 中执行 bin/fess-setup upgrade plugins ,将各插件替换为针对 15.9 构建的版本(参阅 插件版本更新 )。

  4. 确认配置差异,根据需要进行调整

RPM/DEB 版

安装新版本的包:

# RPM
$ sudo rpm -Uvh fess-15.9.0.rpm

# DEB
$ sudo dpkg -i fess-15.9.0.deb

Note

RPM 版中,/etc/fess/* 的配置文件被注册为 %config(noreplace), 因此在升级时会被保留(新的默认文件会以 .rpmnew 的形式并存)。 如果添加了新的配置选项,需要手动调整。修改过的 /etc/fess/fess_config.properties 与 ZIP 版 步骤中复制的文件一样,在 15.9 中仍使用旧值。请参阅 从 15.8 沿用的配置文件

Warning

DEB 版中,/etc/fess/* 并未注册为 conffile(conffile 仅有 /etc/default/fess/etc/init.d/fess/usr/lib/systemd/system/fess.service 这 3 个)。因此执行 dpkg -i 时,/etc/fess/fess_config.properties 等文件会被 新版本的文件覆盖。覆盖时不会确认,也不会保留旧文件的副本,因此请事先备份(步骤 1)。升级后, 请不要原样恢复旧文件,而是将修改内容重新应用到新文件中(参阅 从 15.8 沿用的配置文件 )。 另外,/etc/fess/system.properties 是不包含在软件包中的运行时生成文件, 因此不会被覆盖。

Docker 版

  1. 获取新版本的 Compose 文件:

    $ wget https://raw.githubusercontent.com/codelibs/docker-fess/v15.9.0/compose/compose.yaml
    $ wget https://raw.githubusercontent.com/codelibs/docker-fess/v15.9.0/compose/compose-opensearch3.yaml
    
  2. 获取新镜像:

    $ docker compose -f compose.yaml -f compose-opensearch3.yaml pull
    

步骤 4: 升级 OpenSearch

Fess 15.9 对应 OpenSearch 3.8.0。如果所连接的 OpenSearch 版本比这更旧, 请按照以下步骤升级。

Note

本步骤适用于 ZIP 版及 RPM/DEB 版中手动运维 OpenSearch 的情况。 对于 Docker 版,在步骤 3 中获取新镜像时,OpenSearch 和插件也会一并更新, 因此无需执行本步骤。

Important

无论是否使用分块向量搜索(语义搜索),Fess 15.9 都会在搜索索引的设置中始终 包含 index.knn,并在映射中始终包含 content_chunk_vectorknn_vector 类型)。因此,所连接的 OpenSearch 必须安装 k-NN 插件

  • 标准发行版的 OpenSearch 以及 Docker 版镜像中已包含该插件。

  • minimal 发行版不包含该插件,会导致索引新建失败,|Fess| 无法启动。

  • 索引设置中还会始终发送 knn.derived_source.enabled。无法识别该配置的 旧版本 OpenSearch,无论是否安装 k-NN 插件,索引创建都会失败。

详情请参阅 语义搜索(内容分块 + 向量搜索) 中的「前提条件」。

Warning

OpenSearch 的主版本升级需要谨慎进行。 可能会出现索引兼容性问题。 Fess 14.x 对应 OpenSearch 2.x 系列,因此从 14.x 升级时必然属于这种情况。

  1. 安装新版本的 OpenSearch

  2. 重新安装插件:

    $ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-analysis-fess:3.8.0
    $ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-analysis-extension:3.8.0
    $ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-minhash:3.8.0
    $ sudo /usr/share/opensearch/bin/opensearch-plugin install org.codelibs.opensearch:opensearch-configsync:3.8.0
    

    Note

    这些插件的版本必须与所使用的 OpenSearch 版本一致。 Fess 15.9 对应 OpenSearch 3.8.0。如果版本不一致, 插件安装将会失败。

  3. 启动 OpenSearch:

    $ sudo systemctl start opensearch.service
    

步骤 5: 启动新版本

ZIP 版:

$ cd /path/to/fess-15.9.0
$ ./bin/fess -d -p /path/to/fess-15.9.0/fess.pid

Note

指定 -p 后会创建 PID 文件,下次停止时可以使用 kill $(cat /path/to/fess-15.9.0/fess.pid) 来停止。

RPM/DEB 版:

$ sudo systemctl start opensearch.service
$ sudo systemctl start fess.service

Docker 版:

$ docker compose -f compose.yaml -f compose-opensearch3.yaml up -d

步骤 6: 运行确认

  1. 确认日志

    确认没有错误。

    ZIP 版:

    $ tail -f /path/to/fess/logs/fess.log
    

    RPM/DEB 版:

    $ sudo tail -f /var/log/fess/fess.log
    

    Docker 版:

    $ docker compose -f compose.yaml -f compose-opensearch3.yaml logs -f fess01
    

    Note

    同一日志目录下,还会输出爬取处理的 fess-crawler.log、认证与管理操作的 audit.log、以及检索请求的 searchlog.log

  2. 访问 Web 界面

    在浏览器中访问 http://localhost:8080/

  3. 登录管理页面

    访问 http://localhost:8080/admin 并使用管理员账号登录。

  4. 确认版本

    在管理页面点击「系统信息」→「配置信息」,确认「系统属性」中显示的 fess.version 已更新为新版本。

  5. 确认搜索运行

    在搜索页面执行搜索,确认正常返回结果。

步骤 7: 重建索引(推荐)

对于主版本升级,建议重建索引。

Note

以下步骤只是重新执行爬取,并不会更新索引映射(字段定义)。如果需要进行会更新映射的重新 索引——例如要新启用分块向量搜索(语义搜索)时——请在管理界面的「系统信息」→「维护」中 单独运行「重新索引」。详情请参阅 从 15.7 及更早版本迁移语义搜索(内容分块 + 向量搜索))。

  1. 确认现有爬取计划

  2. 从「系统」→「调度器」执行「Default Crawler」

  3. 等待爬取完成

  4. 确认搜索结果

Warning

由于重新索引会以新的映射重建索引,在没有 k-NN 插件的 OpenSearch 中会失败。 请确认步骤 4 中的注意事项。

从 15.8 升级到 15.9

若从 15.8 升级,以下为不向后兼容的变更。

内嵌 OpenSearch 的移除

15.8 之前,未设置 SEARCH_ENGINE_HTTP_URL 而启动 bin/fess 时,Fess 会在自身的 JVM 内 启动 OpenSearch 节点。15.9 移除了该配置,搜索引擎始终是独立的服务器。

bin/fess.in.sh 现在默认设置 SEARCH_ENGINE_HTTP_URL=http://localhost:9200。 如果没有可连接的 OpenSearch,Fess 将无法启动。可以使用 bin/fess-setup install opensearch 进行安装(仅限 Linux 和 Windows。OpenSearch 没有官方的 macOS 发行版,请使用 Homebrew 或 Docker)。

Fess 还需要 FESS_DICTIONARY_PATH 与该 OpenSearch 的 opensearch.yml 中的 configsync.config_path 一致;否则 Fess 无法创建索引。当 Fess 目录下的 opensearch/ 中恰好只有一个通过 bin/fess-setup install opensearch 安装的 OpenSearch 时,15.9 的 bin/fess.in.sh(Windows 上为 bin\fess.in.bat)会自动设置该变量。使用其他 OpenSearch 时,请按照 在 Linux 上安装(详细步骤)在 Windows 上安装(详细步骤) 的说明进行设置。

以下内容也一并移除:

  • es/ 目录(es/moduleses/pluginses/data

  • -Dfess.es.dirSEARCH_ENGINE_HOME

  • bin/module.xmlbin/plugin.xml

  • 对旧 elasticsearch.* 配置键的回退处理

此外,连接早于 OpenSearch 3 的版本时,15.8 只记录错误日志并继续运行,而 15.9 将启动失败。 这些版本未实现遍历全部文档的处理所依赖的 _shard_doc 排序,通过 HTTP 时此类请求不会失败, 而是不返回响应。

Warning

使用内嵌 OpenSearch 运行时的索引数据无法继承。请新建外部 OpenSearch 服务器,通过管理界面的 「备份」迁移配置后重新爬取。备份包含爬取配置、用户和日志,不包含已爬取的文档

Playwright 爬虫移至插件

Playwright 爬虫及其使用的 Node.js 可执行文件不再包含在发行包中。 在 fess-15.8.0.zip(457.1 MiB)中,收纳 Node.js 可执行文件的 Playwright 驱动包占用了 204.3 MiB。

如果爬取配置的设置参数中指定了 Playwright 客户端(例如 client.crawlerClients=playwright:http://.*),请同时安装插件与 Node.js。 插件也可以从管理界面的「系统 > 插件」页面安装。 bin/fess.in.sh 会检测 Node.js 的安装位置并设置 PLAYWRIGHT_NODEJS_PATH

$ bin/fess-setup install plugin fess-crawler-playwright
$ bin/fess-setup install nodejs

没有插件时,此类配置仍会被爬取,但使用的是普通 HTTP 客户端,因此只有 JavaScript 才会生成的 文本不会被索引。爬取作业仍会正常结束,也不会记录失败 URL。每次爬取时, fess-crawler.log 会按每个爬取配置记录一条警告,其中给出插件名称和上面的两条命令。

如果不使用 Playwright 爬虫,则无需处理。

Google Cloud Storage 移至插件

Google Cloud Storage 的 SDK 不再包含在发行包中, gcs:// 爬取与 gcs 存储类型改由 fess-storage-gcs 插件提供。请从管理界面的「系统 > 插件」页面安装,或执行以下命令。

$ bin/fess-setup install plugin fess-storage-gcs

crawler.file.protocols 的随附取值中也去掉了 gcs,现为 file,smb,smb1,ftp。安装插件后会重新加入。在此之前,路径以 gcs: 开头的文件 爬取配置只会记录一条警告,且什么都取不到。升级后的现有安装会保留自己的 crawler.file.protocols,因此路径仍被接受,但没有可处理它的爬虫客户端;新安装中 gcs: 不是已配置的协议,管理界面会拒绝保存该路径,而先前保存的路径会被当作本地文件 路径处理。存储页面同样会记录警告,并把失败作为错误显示出来,文字中包含需要安装的插件 名称;此前它只显示一个空的文件列表。

如果不使用 Google Cloud Storage,则无需处理。Amazon S3 以及 MinIO 等兼容 S3 的存储也以 同样的方式移至插件,请参阅下一节。

Amazon S3 移至插件

AWS SDK 不再包含在发行包中, s3:// 爬取与 s3s3_compat 存储类型改由 fess-storage-s3 插件提供。请从管理界面的「系统 > 插件」页面安装,或执行以下命令。

$ bin/fess-setup install plugin fess-storage-s3

crawler.file.protocols 的随附取值中也去掉了 s3,现为 file,smb,smb1,ftp。 安装插件后会重新加入。 storage.type 的默认值仍为 auto,未设置端点时会解析为 S3,因此即使从未显式指定 s3,在安装插件之前管理界面的存储功能也无法使用。 storage.* 的取值位于 WEB-INF/conf/system.properties,因此会保留下来,现有的 crawler.file.protocols 也不会被升级覆盖。

如果不使用 Amazon S3 或 MinIO 等兼容 S3 的存储,则无需处理。

SSO 认证移至插件

四种 SSO 认证均不再包含在发行包中,每个 sso.type 取值改由各自的插件提供,插件中同时 附带所需的认证库: saml 对应 fess-sso-samlspnego 对应 fess-sso-spnegoentraid(旧名 aad 亦同)对应 fess-sso-entraidoic 对应 fess-sso-oidc。请注意最后一组:插件名为 fess-sso-oidc,而 sso.type 的取值仍为 oic,两者不一致的地方仅此一处。请从管理界面的 「系统 > 插件」页面安装所需的插件,或执行以下命令。

$ bin/fess-setup install plugin fess-sso-saml

sso.typesaml.*spnego.*entraid.*aad.*oic.* 各项位于 WEB-INF/conf/system.properties,因此设置值会保留下来。管理页面 「系统」→「常规」也仍将四种类型全部列为选项,设置项也保留。这是因为插件无法提供 JSP, 因此该页面不会提示插件尚未安装。

安装插件之前,对 /sso/ 的请求会被重定向回登录页面,页面上会提示 SSO 登录失败,无法 通过 SSO 登录。15.9 会将包含所查找的组件名与提供方插件名的警告记录到 fess.log; 15.8 之前在任何日志级别下都不会输出任何内容。

如果不使用 SSO,即 sso.typenone 或未设置,则无需处理。

内置脚本引擎由 Groovy 改为 JavaScript

15.8 之前内置的脚本引擎为 Groovy, job.default.script 的默认值也是 groovy 。15.9 中内置 引擎为 JavaScript,默认值为 javascript 。Groovy 已不再内置,改由 fess-script-groovy 插件提供;要让 scriptTypegroovy 生效,必须安装该插件。

升级不会更改各设置中保存的脚本引擎,而 15.9 之前保存且未记录引擎的设置会被视为 groovy 。 没有该插件时,以下内容将无法正常工作:

  • groovy 保存的计划任务。 15.8 自行注册的任务也属于这种情况。Default Crawler、Suggest Indexer、Config Reloader、 Log Aggregator、Doc Purger 等随附任务都以 groovy 保存,而 15.9 启动时只会添加尚不存在的 随附任务,因此不会改动它们。这些任务每次按计划触发都会失败,Default Crawler 也不再进行爬取。 大多数随附任务的「日志记录」处于关闭状态,因此失败不会出现在作业日志中,只会在 fess.log 中留下 Failed to execute job 警告。

  • 在「配置参数」中编写了字段脚本( field.script.<字段名> )的 Web 爬取配置和文件爬取配置。 该配置的所有文档都会因 ScriptEngineException 失败并记录为失败 URL,而爬取作业本身仍会 正常结束。

  • 设置了「脚本」的数据存储配置。除参数名本身以外的值无法求值。请参阅 数据存储连接器概述

  • 文档提升规则。该规则不会提升任何文档。

  • 「替换」以 groovy: 开头的路径映射。该映射不会被应用,URL 保持不变。

首次启动后,请在 fess.log 中查找以 Settings use the script engine groovy, which is not registered 开头的警告。Fess 会在 启动时检查一次上述设置,并按类型输出使用了没有任何插件提供的引擎的设置数量。如果从 15.8 沿用的 fess_config.properties 中仍为 job.default.script=groovy ,警告中也会列出该项,此时升级后 新建的任务同样会使用 Groovy(参阅 从 15.8 沿用的配置文件 )。请采用以下任一方式 处理:

  • 安装该插件并重启 Fess 。已保存的 Groovy 脚本可原样运行,警告也不再输出。也可以在管理页面 「系统」→「插件」中安装该插件。

    $ bin/fess-setup install plugin fess-script-groovy
    
  • 将各设置改用 JavaScript。先改写只有 Groovy 才接受的语法,再选择 JavaScript:

    • 计划任务:在管理页面「系统」→「调度器」中将「执行方法」改为 javascript 。随附任务的 脚本除以下两项外,原样即是有效的 JavaScript:Thumbnail Purger 使用了 Groovy 的 long 字面量 1000L ,在 JavaScript 中会成为语法错误(请写成 1000 );Index Exporter 需要进行 Index Exporter 作业引用了已删除的包 中所述的修改。JavaScript 的数组字面量会自动转换为 Java 的 String[] ,因此不再需要 Groovy 写法中的 as String[]

      return container.getComponent("crawlJob").logLevel("info").webConfigIds(["1", "2"]).fileConfigIds(["1"]).dataConfigIds([]).execute(executor);
      
    • Web 爬取配置和文件爬取配置:在「配置参数」中添加 config.script.type=javascript

    • 数据存储配置:在「参数」中添加 script_type=javascript

    • 文档提升规则:将「脚本类型」改为 javascript

    • 路径映射:将「替换」的开头由 groovy: 改为 javascript:

    • job.default.script :在从 15.8 沿用的 fess_config.properties 中将其设置为 javascript

crawler.default.script 已删除

fess_config.properties 中已不存在 crawler.default.script 。请从配置中删除该项; 以该名称保留的值不会生效。

爬取协议 storage 已删除

crawler.file.protocols 中不再接受 storage ,随附的值为 file,smb,smb1,ftp 。 请改用 s3 ,并将路径以 storage: 开头的文件爬取配置改为 s3: 路径。 s3 需要 fess-storage-s3 插件。

Index Exporter 作业引用了已删除的包

15.9 不再包含 org.opensearch 的类,作业脚本使用的查询构建器已移至 org.codelibs.fesen.opensearch 下。15.8 为 Index Exporter 作业保存的脚本引用了 org.opensearch.index.query.QueryBuilders ,而升级不会替换该脚本,因此即使安装了 fess-script-groovy ,该作业仍会失败。该作业随附时处于禁用状态且没有计划,因此只有在运行它时 才会受到影响。请在管理页面「系统」→「调度器」中打开该作业,将脚本中的包改为 15.9 所用的包:

return new org.codelibs.fess.job.IndexExportJob().query(org.codelibs.fesen.opensearch.index.query.QueryBuilders.matchAllQuery()).execute()

如果自行编写的脚本中引用了 org.opensearch.index.query ,也请以同样方式修改。更多查询示例请 参阅 索引导出功能

从 15.8 沿用的配置文件

步骤 3 的 ZIP 版步骤会从旧安装中复制 fess_config.propertiesbin/fess.in.sh ;RPM 版 升级则会保留修改过的 /etc/fess/fess_config.properties (15.9 的文件以 fess_config.properties.rpmnew 的形式并存)。无论哪种情况,15.9 都会以 15.8 的值运行,15.9 中随附值已变更的键也不例外。请至少确认以下各键。

15.8.0 15.9 保留 15.8 的值时的影响
job.default.script groovy javascript

在管理页面「系统」→「调度器」中新建的作业默认使用 groovy ,没有 fess-script-groovy 插件时会失败。

job.template.script as String[] 的 Groovy 写法 JavaScript 写法 从爬取配置创建的作业会得到 Groovy 脚本。
crawler.file.protocols file,smb,smb1,ftp,storage,s3,gcs file,smb,smb1,ftp

s3:gcs: 开头的路径即使没有对应插件也会被接受,爬取时记录警告并跳过。 storage 已不再受支持。

search_engine.http.url http://localhost:9201 http://localhost:9200

在未设置 SEARCH_ENGINE_HTTP_URL 时使用。从 15.8 复制的 bin/fess.in.sh 中未设置 该变量时即属于这种情况,此时 Fess 会在 9201 端口查找 OpenSearch,即 15.9 已移除的内嵌 OpenSearch 所用的端口。

jvm.crawler.optionsjvm.thumbnail.options -Djcifs.smb.client.*-Djcifs.smb1.smb.client.* -Djcifs.client.* SMB 超时保持为 jcifs 的默认值。请参阅 SMB 超时改用 jcifs 3 的属性名

crawler.default.scripttheme.allowed.archive.extensionstheme.assets.cache.max.agetheme.assets.precompressedrag.chat.message.max.lengthsupported.uploaded.js.extentionssupported.uploaded.css.extentionssupported.uploaded.media.extentionssupported.uploaded.filesonline.help.name.design

存在 已删除 不起作用,请删除。

从 15.8 复制的 bin/fess.in.sh 还缺少 15.9 文件中的以下两点。15.9 会将 SEARCH_ENGINE_HTTP_URL 设置为 http://localhost:9200 ,而 15.8 的文件除非自行设置,否则 保持未设置状态。此外,它不会查找通过 bin/fess-setup install nodejs 安装的 Node.js,因此除非 自行设置 PLAYWRIGHT_NODEJS_PATH ,否则 Playwright 爬虫找不到 Node.js。

请不要整体复制这两个文件,而是以 15.9 随附的文件为基础,重新应用自己修改过的值。可以用 diff 查看这些值:

$ diff /path/to/old-fess/app/WEB-INF/classes/fess_config.properties /path/to/fess-15.9.0/app/WEB-INF/classes/fess_config.properties
$ diff /path/to/old-fess/bin/fess.in.sh /path/to/fess-15.9.0/bin/fess.in.sh

RPM 版请以同样方式比较 /etc/fess/fess_config.properties/etc/fess/fess_config.properties.rpmnew 。DEB 版升级则会覆盖 /etc/fess/fess_config.properties (参阅步骤 3),因此从 15.9 的值开始,只需重新应用自己的 修改。

SMB 超时改用 jcifs 3 的属性名

Fess 爬取 SMB 文件服务器时使用的 jcifs 在版本 3 中更改了属性名: jcifs.smb.client.* 改为 jcifs.client.* ,SMB1 专用的 jcifs.smb1.smb.client.* 也合并到了相同的属性中。15.8 之前, jvm.crawler.optionsjvm.thumbnail.options 仍传递旧名称,而 jcifs 不读取这些名称,因此 SMB 爬取一直以 jcifs 的默认值运行。15.9 传递新名称:

-Djcifs.client.responseTimeout=30000
-Djcifs.client.soTimeout=35000
-Djcifs.client.connTimeout=60000
-Djcifs.client.sessionTimeout=60000

因此,连接超时与会话超时首次生效,从 jcifs 默认的 35 秒延长到 60 秒:对于没有响应的 SMB 服务器,爬取现在最多会等待 60 秒。响应超时与套接字超时与 jcifs 的默认值相同,因此不会变化。

如果修改过这些超时,请在两个选项中改用新名称。使用旧名称时,它们在 15.8 中同样不起作用。从 15.8 沿用的 fess_config.properties 会保留旧名称,也就仍使用 jcifs 的默认值。

删除了四个不起作用的属性

以下键已从 fess_config.properties 中删除。Fess 从未从该文件读取它们,因此以这些名称保留的 值与以前一样不起作用。

  • theme.allowed.archive.extensions

  • theme.assets.cache.max.age

  • theme.assets.precompressed

  • rag.chat.message.max.length

rag.chat.message.max.length 设定的上限仍然有效,但会作为系统属性读取:请按照 AI搜索模式功能配置 中的说明,在 app/WEB-INF/conf/system.properties 中或通过 -Dfess.system.rag.chat.message.max.length 进行设置。

删除了管理界面的「页面设计」

删除了管理界面中的 [系统 > 页面设计]。无法再从管理界面编辑搜索界面的 JSP、CSS 和图片。 如需更改搜索界面的外观,请使用静态主题(参见 主题开发指南)。

以下键也已从 fess_config.properties 中删除。以这些名称保留的值不会被使用。

  • supported.uploaded.js.extentions

  • supported.uploaded.css.extentions

  • supported.uploaded.media.extentions

  • supported.uploaded.files

  • online.help.name.design

admin-designadmin-design-view 角色不再授予任何权限。仅拥有这些角色的用户登录后会进入 搜索界面,而不是管理界面。

15.9 特有的迁移工作

从 15.7 及更早版本升级到 15.9 时,需要根据所使用的功能执行以下工作。

若此前使用过语义搜索

在 Fess 15.7 及更早版本中提供语义搜索功能的 fess-webapp-semantic-search 插件, 已在 15.9 中并入核心,现已不再需要(已弃用)。需要移除该插件、删除 -Dfess.semantic_search.*-Drank.fusion.searchers=default,semantic, 并解除旧的 ingest pipeline。详细步骤请参阅 从 15.7 及更早版本迁移语义搜索(内容分块 + 向量搜索))。

若此前使用过 AI 搜索模式(RAG Chat)

自 15.9 起,AI 搜索模式(RAG Chat)功能已拆分为 fess-llm-ollamafess-llm-openaifess-llm-gemini 等插件。请在管理页面「系统」→「插件」中安装与所使用的 提供商对应的插件。

若此前使用过 SPNEGO(Windows 集成认证)

自 15.9 起,如果客户端主体的 Kerberos 领域与服务器的领域不同,SPNEGO 登录将被拒绝。 如果用户来自 AD 域树的子域或建立了信任关系的林,请在管理页面「系统」→「通用」或 app/WEB-INF/conf/system.propertiesspnego.allowed.realms 中以逗号分隔列出 这些领域。否则,在 15.7 之前能够登录的用户将因 Kerberos realm is not allowed 而被拒绝。 详细内容请参阅 Windows集成认证SSO配置

此外,15.9 中 spnego.allow.unsecure.basicspnego.allow.localhost 的代码默认值也从 true 改为了 false 。在 app/WEB-INF/conf/system.properties 中不存在这些键的环境中, 升级后会自动采用更严格的行为。特别是当 spnego.allow.unsecure.basic=false 时,SPNEGO 库仅对 HttpServletRequest#isSecure() 返回 true 的请求提供 Basic 认证, 因此在反向代理上终止 TLS 并以 HTTP 转发的环境中,此前回退到 Basic 认证的客户端将无法登录。 此时请在 tomcat_config.properties 中设置 tomcat.secure=true 。 详细内容请参阅 Windows集成认证SSO配置

Warning

代码默认值仅在该键不存在时才生效,而管理页面「系统」→「通用」每次保存都会写入所有 spnego.* 键。因此,在 15.7 中曾经在该页面上执行过更新的环境,仍然保存着 spnego.allow.unsecure.basic=truespnego.allow.localhost=true , 升级到 15.9 并不会使其变得更严格:宽松的行为会被静默沿用,15.9 只会在 SPNEGO 初始化时 向 fess.log 输出一条警告。请在管理页面「系统」→「通用」或 system.properties 中 有意识地关闭这两项。其中 spnego.allow.localhost=true 更为危险:SPNEGO 库会把来自同一 主机的请求以服务器的 OS 用户身份进行认证,完全不做 Kerberos 验证,在同一主机上部署反向 代理时并不安全。

若此前使用过 SAML 认证(SSO)

自 15.9 起,Fess 会将每个 SAML 响应与自身发出的 AuthnRequest 的 ID 进行绑定校验, 因此 IdP 发起(未经请求的 unsolicited)的 SSO 无法再使用。从 IdP 门户(如 Okta 仪表板或 Microsoft Entra ID 的「我的应用」)中的 Fess 磁贴发起的登录没有可匹配的 AuthnRequest, 会被拒绝。在 15.7 之前它之所以可用,是因为 Fess 会将无法匹配的响应退回给 IdP, 而 IdP 会立即返回一个经过请求的断言。如果要在 IdP 侧放置磁贴,请将其链接指向 Fess 的 /sso/ 端点,使登录由 SP 发起。

此外,IdP 通过跨站 POST 返回断言,因此必须将 tomcat_config.properties 中的 tomcat.sameSiteCookies 设置为 none。使用附带的默认值 lax 时,会话 Cookie 不会随该请求发送,SAML 登录无法完成。该文件在 ZIP 软件包中位于 lib/classes/, 在 DEB/RPM 软件包中位于 /etc/fess/,修改后需要重启 Fess。浏览器仅对同时带有 Secure 属性的 Cookie 接受 none,因此 Fess 必须通过 HTTPS 提供服务。 在 15.7 之前,同样的配置错误不会产生明确的错误,而是表现为不断重定向到 IdP 的死循环, 因此即使站点看起来正常,也请确认该设置。15.9 不再循环,而是一次性失败。 详细内容请参阅 SAML认证SSO配置

若此前使用过 Microsoft Entra ID(Azure AD)

自 15.9 起,向授权端点请求的响应模式默认值由 form_post 变更为 query。15.7 之前回调以 跨站 POST 返回,而 Fess 的默认值 tomcat.sameSiteCookies = lax 不会随该请求发送会话 Cookie,因此需要将其改为 tomcat.sameSiteCookies = none。如果仅为此才设置了 none, 可以恢复为默认值。若要保持原有行为,请指定 entraid.response.mode=form_post 并保留 tomcat.sameSiteCookies = none。浏览器仅对同时带有 Secure 属性的 Cookie 接受 none,因此这种方式同样要求通过 HTTPS 提供 Fess 。

自 15.9 起,Fess 还会在登录完成后于后台解析用户所属的组和角色,而不再让登录等待 Microsoft Graph。在解析完成之前——或解析未能完全成功时——用户拥有的仅有其自身的用户级权限,以及在 entraid.default.groupsentraid.default.roles 中配置的组和角色。若两者都未配置 (即附带的默认值),这段时间内的搜索将一条文档都搜不到,因为按附带的默认值创建的爬取配置会授予 {role}guest,而已登录用户并不持有该角色。解析进行期间,搜索界面会显示相应提示, 未能完全成功时则显示另一条提示(只有直接所属查询和嵌套组遍历都成功,解析才算成功)。 每次刷新访问令牌时都会重新解析,之后一旦成功,提示即会消失,因此对于持续时间超过令牌有效期的会话,失败并不一定就是 最终结果;若要立即重试,请先注销再重新登录。 详细内容请参阅 Microsoft Entra ID SSO配置

在后台解析还带来一个影响:在解析完成之前,尚无法得知用户已解析的角色。因此, 管理员会被重定向到搜索界面而不是管理仪表板,在此期间打开管理页面也会被送回搜索界面。 这段时间为最多约 1 秒的调度延迟,加上 Microsoft Graph 调用本身(直接所属查询 1 次, 再为每个直接所属的组各 1 次以遍历嵌套组,依次串行执行,且缓存为空时), 因此会随用户所属组的数量增加而变长。在此期间访问只会被拒绝,绝不会被放行;而且无需任何配置即可度过这段时间:授权会在同一会话的每个请求上 重新评估,因此解析完成后重新打开管理界面即可正常访问,无需重新登录。

Warning

请勿通过把 Fess 的管理员角色配置到 entraid.default.roles 来缩短这段时间。 该属性是单个全局值,Fess 会在登录时将其应用于每一个 Entra ID 用户, 并在之后每次解析时重新应用,这会让租户中的所有用户永久获得 Fess 管理员权限。

使用 LDAP / Active Directory 集成的情况

从 15.9 开始,组和角色的权限名称取自条目 RDN 的值,而不再是从 DN 文本中截取的片段。CN 中包含 在 DN 内被转义的字符(通常是逗号)的组,其权限名称将与 15.7 之前不同。

组条目的 DN 15.7 之前的权限名称 15.9 的权限名称
CN=Sales\, EMEA,CN=Users,... 2Sales 2Sales, EMEA
CN=Sales\, APAC,CN=Users,... 2Sales 2Sales, APAC

在 15.7 之前,逗号之前部分相同的多个组会合并为同一个权限名称,因此 Sales, EMEASales, APAC 的成员可以读取对方的文档以及 Sales 组的文档。在 15.9 中,各自获得独立的权限 名称,这种跨组访问不会再发生。

作为代价,以旧权限名称索引的文档将不再对该组的用户可见。如果爬取设置的「权限」中配置了 旧的权限名称,请更新为新的权限名称并重新爬取(或重新索引)。如果没有使用 CN 中包含逗号等转义字符 的组,权限名称不会发生变化。

ldap.role.search.user.enabled 的行为变更

在 15.7 之前,即使设置了 ldap.role.search.user.enabled=false,仍会授予从用户名派生的权限 (role.search.user.prefix 加用户名)。从 15.9 开始该设置将实际生效,为 false 时不再授予。

在设置为 false 的环境中,升级后用户会失去以自身命名的权限,因此针对单个用户设置了权限的文档 将无法被该用户检索到。若要保持原有行为,请恢复为随附的默认值 true

若此前修改过 /api/v2 配置键

从 15.8.0 起,有四个配置键去掉了 api.v2. 前缀。其取值、默认值和行为均未改变,但没有保留向后兼容的别名:仍使用旧名称的设置会被静默忽略,实际生效的是随附的默认值。

15.7 及以前 15.8.0 及以后 默认值
api.v2.chat.stream.keepalive.interval.ms api.chat.stream.keepalive.interval.ms 15000
api.v2.param.max.length api.param.max.length 1000
api.v2.param.max.array.size api.param.max.array.size 100
api.v2.click.max.rt api.click.max.timestamp 9999999999999

如果曾在 fess_config.properties 中或通过 -Dfess.config.<键> JVM 参数设置过这些键,请改用新名称。只有显式设置过的情况才会受影响;从未修改过的环境无需处理。

第一个键决定 POST /api/v2/chat/stream 等待模型响应期间发送 keep-alive 帧的间隔,因此设置失效会在 AI 搜索模式中显现。最后一个键的改名也是为了更准确:它限制的是点击日志中rt 的取值上限,而该值是时间戳而非响应时间。

插件版本更新

安装在 app/WEB-INF/plugin/ 中的插件,需要替换为与 Fess 版本对应的版本。 bin/fess-setup upgrade plugins 会针对所有已安装的插件,安装为此 Fess 构建的版本并删除旧版本。 之后请重启 Fess 。 bin/fess-setup check 会报告 OpenSearch 及其插件、已安装的 Fess 插件的 状态,出现问题时以退出码 1 结束。

$ bin/fess-setup upgrade plugins
$ bin/fess-setup check

upgrade plugins 只处理已安装的插件。 fess-script-groovy 等用于补充 15.9 从发行包中移除 部分的插件,请按照前面各节的说明,使用 bin/fess-setup install plugin 安装。

如果在 Docker 版中指定了 FESS_PLUGINS,请按照 fess-ds-wikipedia:15.9.0 的形式更新版本号部分。

回滚步骤

如果升级失败,可以按照以下步骤回滚。

步骤 1: 停止新版本

$ sudo systemctl stop fess.service
$ sudo systemctl stop opensearch.service

步骤 2: 恢复旧版本

从备份恢复配置文件和数据。

RPM/DEB 版的情况:

$ sudo rpm -Uvh --oldpackage fess-<old-version>.rpm

或:

$ sudo dpkg -i fess-<old-version>.deb

步骤 3: 恢复数据

从快照恢复:

$ curl -X POST "http://localhost:9200/_snapshot/fess_backup/snapshot_1/_restore?wait_for_completion=true"

或从备份恢复目录:

$ sudo systemctl stop opensearch
$ sudo rm -rf /var/lib/opensearch/data/*
$ sudo tar xzf /backup/opensearch-data-backup.tar.gz -C /
$ sudo systemctl start opensearch

Docker 版中,请先切换回旧版本的 Compose 文件,再恢复卷中的内容:

$ docker compose -f compose.yaml -f compose-opensearch3.yaml down
$ PROJECT=$(basename "$(pwd)")
$ docker run --rm -v ${PROJECT}_search01_data:/data -v $(pwd):/backup ubuntu \
    sh -c "rm -rf /data/* && tar xzf /backup/search01-data-backup.tar.gz -C /"
$ docker compose -f compose.yaml -f compose-opensearch3.yaml up -d

Note

从管理页面下载的配置数据,可在 Fess 启动后,通过「系统信息」→「备份」 页面的上传功能重新导入并恢复。可以上传的文件仅限于 *.bulk、以 system开头的 *.properties、以 gsa开头的 *.xml、 以 fess开头的 *.json、以 doc开头的 *.json,且每次操作只能上传 1 个文件。 搜索日志等 *.ndjson 文件不被接受,会导致错误。

Warning

上传 fess.jsondoc.json 会覆盖 Fess 自带的索引定义文件本身。 升级后如果上传旧版本的 fess.jsondoc.json,会导致新版本的索引设置和映射丢失。 请勿在回滚以外的目的下上传这些文件。

Note

上传的 system.properties 仅会加载到内存中,不会写入文件。 因此 system.properties 的内容会在 Fess 重启后丢失。 如需确保可靠恢复,请将备份的文件直接放置到指定位置(ZIP 版为 app/WEB-INF/conf/,RPM/DEB 版为 /etc/fess/)后再启动。

Note

导入操作以异步方式执行,画面上仅会显示已开始的提示。 请通过 fess.log 确认是否真正成功。

步骤 4: 启动和确认服务

$ sudo systemctl start opensearch.service
$ sudo systemctl start fess.service

确认运行并验证已恢复正常。

常见问题

Q: 可以无停机时间升级吗?

A: Fess 的升级需要停止服务。要最小化停机时间,请考虑以下方法:

  • 提前在测试环境确认步骤

  • 提前获取备份

  • 确保充足的维护时间

Q: 需要升级 OpenSearch 吗?

A: 每个 Fess 版本对应特定的 OpenSearch 版本。 Fess 15.9 对应 OpenSearch 3.8.0。 由于 opensearch-analysis-fess 等 Fess 专用 OpenSearch 插件必须与 OpenSearch 版本完全一致, 因此在升级 OpenSearch 时,请同时将插件更新为对应版本(3.8.0)。

另外,Fess 15.9 强制要求安装 k-NN 插件,并会在索引设置中始终发送 knn.derived_source.enabled。如果 OpenSearch 版本过旧,会导致新索引创建失败, 因此实质上必须升级 OpenSearch。详情请参阅步骤 4。

Q: 需要重建索引吗?

A: 对于 Fess 的小版本升级(15.x → 15.9),如果不使用分块向量搜索, 通常不需要重建索引。现有索引可以直接使用,content_chunker.enabled 等选项默认为 禁用,因此行为不会改变。

以下情况需要重建索引并重新索引。

Warning

新建索引的操作(包括重新索引)在没有 k-NN 插件的 OpenSearch 中会失败。 请确认步骤 4 中的注意事项。

Q: 升级后搜索结果不显示

A: 请确认以下内容:

  1. 确认 OpenSearch 是否启动

  2. 确认索引是否存在(curl http://localhost:9200/_cat/indices

  3. 重新执行爬取

下一步

升级完成后: