Skip to content

运维 ​

本文介绍 ProjectWikit 实例的日常运维:系统服务、日志、备份、升级以及恢复访问。首次安装 pwikit 和注册服务的方法参见部署。文中用到的所有命令均在命令行中有详细说明。

示例假定 pwikit 在 Linux 和 macOS 上安装于 /opt/pwikit,在 Windows 上安装于 C:\pwikit,数据目录与可执行文件位于同一目录。

管理系统服务 ​

pwikit service install 以 pwikit 为名将 pwikit serve 注册到操作系统。若安装时指定了 -name,下列每条命令都需要指定相同的 -name。

sh
pwikit service start
pwikit service stop
pwikit service status
pwikit service uninstall

在 Linux 和 macOS 上请使用 sudo 执行,在 Windows 上请在以管理员身份运行的终端中执行。status 在 Linux 和 Windows 上可由任意账户执行。

  • Linux。 服务即 systemd 单元 /etc/systemd/system/pwikit.service,因此也可以使用 systemctl 管理。
  • macOS。 使用 sudo 安装的服务为 /Library/LaunchDaemons/pwikit.plist,随开机启动。不使用 sudo 安装的服务为 ~/Library/LaunchAgents/pwikit.plist,在登录时启动,管理时也无需 sudo。以其中一种方式安装的服务,用另一种方式无法看到。
  • Windows。 服务在“服务”管理器中显示为 ProjectWikit,以虚拟账户 NT SERVICE\pwikit 运行。

停止服务时,pwikit 最多有三分钟时间完成关闭,包括停止其 PostgreSQL。停止服务不会阻止它在下次开机时启动;uninstall 才会。uninstall 还会删除 install 添加的防火墙规则,并关闭其开放的端口。

pwikit 意外停止时 ​

pwikit 以错误状态退出时,服务管理器会自动重新启动它。若内置 PostgreSQL 在 pwikit 运行期间停止,pwikit 会随之停止并记录原因,重启时两者一并重新启动。非正常停止之后,PostgreSQL 需要先重放日志才能就绪,这可能需要一些时间。

在服务运行时执行命令 ​

pwikit backup create、pwikit site list 等命令可以在服务运行期间执行;使用内置 PostgreSQL 时,它们会使用服务启动的 PostgreSQL。在 Linux 和 macOS 上,请以服务所用的账户执行,而不要以 root 执行:

sh
sudo -u wiki /opt/pwikit/pwikit backup create

日志 ​

pwikit 日志 ​

运行方式日志位置
在终端中运行标准错误输出,或 -log-file 指定的文件
Linux 服务systemd 日志:journalctl -u pwikit -f
macOS 服务logs/pwikit.log;崩溃信息以及日志文件打开之前的输出写入 logs/pwikit-stderr.log
Windows 服务logs/pwikit.log。服务因错误停止时,错误还会写入 Windows 事件日志(“应用程序”日志,来源为 pwikit)

日志文件达到 10 MB 时轮转,保留 5 份旧文件。

PostgreSQL 日志 ​

pwikit 运行内置 PostgreSQL 时,PostgreSQL 的日志写入数据目录下的 logs/,只保留最近一周。PostgreSQL 无法启动时,原因见 logs/postgresql-start.log。

使用自己的 PostgreSQL 时,其日志位于该服务器自身的日志位置。

备份 ​

备份的内容 ​

pwikit backup create 写入一个 .pwbak 文件,其中包含:

  • 数据库中的所有表:全部站点、账号、页面及其历史记录、论坛和设置;
  • files/ 中的上传文件(指定 -no-files 时除外);
  • 一份清单,记录备份的创建时间、创建它的 pwikit 版本、PostgreSQL 版本、数据库已应用的结构迁移,以及每个表和文件的行数与校验和。

备份不包含 pwikit.toml、secrets/、logs/ 和可执行文件。请另行保存 pwikit.toml 和 secrets/ 的副本,参见 secrets 目录。

备份是逻辑备份,而不是 pgdata/ 的副本,可以在另一台机器上恢复到内置 PostgreSQL 或您自己的 PostgreSQL 中,PostgreSQL 版本也可以不同(14 或更高)。

创建备份 ​

sh
pwikit backup create

文件写入 backups/pwikit-<UTC time>.pwbak;使用 -output 可指定其他路径。备份可以在 pwikit 提供服务期间进行:所有表在同一个一致的快照中读取,上传文件在表之后读取。运行期间,表数据会暂存在系统临时目录中,因此该目录需要大致相当于数据库大小的可用空间。中断的备份不会在最终文件名下留下文件。

校验与列出备份 ​

sh
pwikit backup list
pwikit backup verify backups/pwikit-20260911-030000.pwbak

list 列出 backups/ 中的备份。verify 完整读取文件,报告损坏或缺失的内容,以及由更新版本的 pwikit 创建的备份。这两个命令都无需数据库。

恢复备份 ​

恢复会替换整个数据库;备份包含上传文件且未指定 -no-files 时,也替换上传文件。

  1. 停止 pwikit:

    sh
    sudo ./pwikit service stop
  2. 执行恢复:

    sh
    pwikit backup restore backups/pwikit-20260911-030000.pwbak -force
  3. 重新启动 pwikit。

必须先停止 pwikit。 若 pwikit serve 或其他程序仍连接着数据库,恢复会报错终止,不做任何更改。请停止服务或占用连接的程序后重新执行命令。

-force。 已有站点、账号或页面等数据的数据库,仅在指定 -force 时才会被替换。未指定时,命令终止且不做任何更改。只含 pwikit 首次启动时写入的内容的数据库视为空数据库,因此已启动过一次但尚未创建站点的新实例无需指定 -force。

安全备份。 在进行任何更改之前,restore 会将当前的数据库和文件备份到 backups/before-restore-pwikit-<UTC time>.pwbak 并输出其路径。若这份备份失败,则不做任何更改。如需撤销本次恢复,恢复这份文件即可。指定 -no-safety-backup 可跳过这一步。指定 -no-files 时,由于文件不会被改动,安全备份不包含文件。数据库中尚无数据时跳过这一步。

恢复过程。

  1. 完整校验备份。备份损坏时拒绝恢复,不做任何更改。
  2. 在同一个事务中清空数据库并从备份重新填入数据。任何一步失败,数据库均保持原状。
  3. 若备份由较旧的 pwikit 创建,则应用此后新增的结构迁移。
  4. 若备份包含上传文件,文件先写入 files/ 旁边的目录,再整体替换。原目录保留为 files.replaced;已存在的旧 files.replaced 会先被删除。确认无误后请自行删除 files.replaced。使用不含文件的备份,或恢复时指定 -no-files,都不会改动 files/。

由更新版本的 pwikit 创建的备份会被拒绝,且不做任何更改。请使用该版本或更新版本的 pwikit 进行恢复。

恢复到您自己的 PostgreSQL。 在 PostgreSQL 14 或更高版本上创建一个空数据库(服务器需提供 citext 和 pg_trgm 扩展),然后执行:

sh
pwikit backup restore backups/pwikit-20260911-030000.pwbak \
  -database "postgres://pwikit:secret@db.internal:5432/pwikit"

上传文件仍写入数据目录下的 files/。之后在 pwikit.toml 中设置 database(或使用 -database、DATABASE_URL),使 pwikit serve 使用该数据库,参见配置。

恢复失败或没有生效时 ​

恢复失败时,命令会打印原因并以错误状态退出。按以下顺序检查:

  1. 阅读命令输出的最后几行,其中给出了失败的原因。
  2. 执行 pwikit backup verify <备份文件>,确认文件完好。若报告校验和不符,通常是复制或上传不完整,请重新复制该文件。
  3. 执行 pwikit service status,确认服务已停止,然后重新执行恢复命令。

恢复命令没有报错,但 pwikit site list 列出的仍是恢复前的站点时:

  • 查看 backups/ 中有没有本次生成的 before-restore-pwikit-<UTC time>.pwbak。 有,说明恢复已经开始,但在写入数据库时失败,数据库保持原状,请按上面的步骤检查后重试;没有,说明恢复在开始之前就终止了,例如服务仍在运行。指定了 -no-safety-backup 或数据库中尚无数据时,本来就不会生成这份文件。
  • 确认命令与服务使用同一个数据目录。 命令默认使用 pwikit 可执行文件所在的目录作为数据目录,即使是通过 PATH 中的 pwikit 执行的。服务安装时若指定了其他 -data-dir,执行命令时也要加上同样的 -data-dir。在 Linux 上,可以在 systemctl cat pwikit 输出的 ExecStart 一行中看到服务所用的数据目录。

导出单个站点 ​

sh
pwikit backup create -site main

-site 为单个站点写入备份,文件名为 pwikit-<slug>-<UTC time>.pwbak,用于将该站点迁移到新实例。其校验和恢复方式与其他备份相同。

包含不包含
站点及其站点设置其他站点
页面及其版本、作者、标签、评分、收藏、页面历史记录和搜索索引用户之间的私信和屏蔽关系
其页面的附件记录通知
分类及其权限设置、标签与标签分类、主题账号的登录地址记录,用于 可疑活动
身份组与身份组分类,及其权限和成员会话:所有人都需要重新登录
论坛版块、论坛分类、论坛主题、帖子、帖子版本和点赞与该站点无关的账号
邀请链接、用户检举、支持工单、操作记录
对其页面和论坛主题的关注
其页面的反向链接;指向本实例其他站点的链接不再记录目标站点
以上任何内容涉及的所有账号及其偏好设置

上传文件。 files/ 目录由实例中的所有站点共用,-site 会将其整个包含在内,其中也包括其他站点的文件。若其他站点的文件不得带出实例,请指定 -no-files;此时导出不含附件。

账号。

  • 所有导出账号的超级管理员权限均被移除,机器人账号的 API 密钥 被清除。新实例的运营者需自行设立管理员。
  • 未指定 -keep-passwords 时,导出的账号没有可用的密码。账号所有者可通过登录页上的 忘记密码 设置新密码;这需要新实例已配置邮件,且仅适用于邮箱已验证的已启用账号。由于这类账号没有密码,也可以通过 pwikit admin create -name <name> 接管。
  • 指定 -keep-passwords 时,账号保留原密码,所有者可照常登录。可通过 pwikit admin grant -name <name> 将其中一人设为管理员。

导入单站导出。 使用 pwikit backup restore 将其恢复到新实例。

注意 恢复总是替换整个数据库。不支持将站点添加到已有站点的实例中:在这样的实例上使用 -force 恢复单站导出,会删除实例中原有的站点。

在新实例上,无论是否已运行过 pwikit serve,数据库中都尚无数据:

sh
pwikit backup restore pwikit-main-20260911-030000.pwbak

之后创建管理员(见上文)并启动 pwikit。若站点迁移到新域名,请在启动前执行 pwikit site rebind。

备份计划建议 ​

  1. 通过系统计划任务每天备份,并以拥有数据目录的账户执行。在 Linux 或 macOS 上,写入该账户的 crontab:

    text
    30 3 * * * /opt/pwikit/pwikit backup create

    在 Windows 上,在“任务计划程序”中创建每日任务,以能够读取数据目录的账户执行 C:\pwikit\pwikit.exe backup create。

  2. 将 backups/ 中的文件复制到另一台机器或存储上。与实例位于同一磁盘的备份会随该磁盘一同丢失。

  3. 在同一位置保存 pwikit.toml 和 secrets/ 的副本,并在其发生变化时更新。

  4. 定期对副本执行 pwikit backup verify。

  5. 自行删除旧备份。pwikit 不会删除 backups/ 中的任何文件,包括 before-restore- 开头的文件。

  6. 每次升级前执行 pwikit backup create。

重建搜索索引 ​

页面在保存时进入站点的搜索索引。若搜索结果中缺少页面,可将它们重新写入索引:

sh
pwikit reindex
pwikit reindex -all

该命令读取站点的每个页面,并输出 <slug>: <n> pages indexed。站点运行期间也可执行。参见命令行。

升级 pwikit ​

以系统服务方式运行的实例会自动更新,也可以执行 sudo pwikit update 手动更新。更新前的准备、失败时的自动回档与手动回档,见更新与回档。

需要手动替换可执行文件时(例如在未以系统服务方式运行的实例上,或无法使用 pwikit update 时):

  1. 停止服务。
  2. 执行备份:pwikit backup create。
  3. 用新的 pwikit 可执行文件替换旧文件,路径保持不变。服务引用的是该路径,因此无需重新安装服务。
  4. 启动服务。

启动时,新的 pwikit 会更新 postgres/ 中的内置 PostgreSQL(pgdata/ 中的数据保留),并应用新的结构迁移。若新版本携带了新的 PostgreSQL 主版本,参见迁移到新的 PostgreSQL 主版本。之后执行 pwikit migrate status 检查结果,每一行都应为 applied。

若要启动时不应用迁移,请使用 pwikit serve -no-migrate(安装服务时可在 -- 之后加上 -no-migrate),之后再通过 pwikit migrate up 应用。

回到旧版 pwikit。 新版本的结构迁移若全部兼容旧版本,旧版 pwikit 可以直接在该数据库上运行,pwikit migrate status 将这些迁移列为 newer。含有不兼容的迁移时,旧版 pwikit 拒绝启动,这些迁移列为 newer-breaking;请使用 pwikit update rollback,或使用旧版 pwikit 并指定 -force 恢复升级前的备份。见旧版本与数据库。

迁移到新的 PostgreSQL 主版本 ​

内置 PostgreSQL ​

以系统服务方式运行的实例,执行 sudo pwikit update 会自动完成下文的全部步骤,见内置 PostgreSQL 的主版本。以下是手动操作的方法。

PostgreSQL 的一个主版本无法读取另一个主版本写入的数据。当新版 pwikit 携带的 PostgreSQL 比写入 pgdata/ 的版本更新时,它不会启动任何程序,也不做任何更改,而是报错退出。迁移数据的步骤如下:

  1. 停止服务,将旧版 pwikit 可执行文件放回原处。

  2. 使用旧版可执行文件执行 pwikit backup create,并记下输出的文件名。

  3. 放入新版可执行文件。

  4. 将 pgdata/ 改名,例如改为 pgdata.old。

  5. 启动服务。pwikit 会创建一个新的空 pgdata/。

  6. 停止服务。

  7. 执行恢复。新数据库中尚无数据,因此无需指定 -force,也不会进行安全备份:

    sh
    pwikit backup restore backups/pwikit-20260911-030000.pwbak
  8. 启动服务并检查各站点。确认无误后删除 pgdata.old。

您自己的 PostgreSQL ​

pwikit 需要 PostgreSQL 14 或更高版本。在较旧的服务器上,pwikit serve 会拒绝启动。请通过 pwikit backup create 备份,再通过 pwikit backup restore <file> -database <new server> 恢复到较新的服务器,然后让 pwikit 使用新服务器。原地升级您自己的服务器请使用 PostgreSQL 自带的工具。

secrets 目录 ​

数据目录下的 secrets/ 保存 pwikit 为自身生成的值。在 Linux 和 macOS 上,该目录创建时仅允许 pwikit 运行所用的账户读取。请确保其不被他人访问,并与备份一同保存其副本:pwikit backup create 不包含该目录。

文件存在条件用途丢失后
session-key未设置 -secret-key 或 SECRET_KEY签名登录 Cookie 和邮件中的链接。能读取它的人可以伪造登录pwikit 会生成新的密钥。所有人都会被登出,已通过邮件发出的链接失效
postgres-passwordWindows 上使用内置 PostgreSQLpwikit 连接内置 PostgreSQL 所用的密码。在 Linux 和 macOS 上,内置 PostgreSQL 不使用密码,只接受 pwikit 运行所用的账户pwikit 会生成现有 pgdata/ 不接受的新密码,从而无法连接。请放回原文件。若没有副本,请将 pgdata/ 移走,启动 pwikit 创建新的数据目录,停止后再恢复备份
certs/-tls=auto通过 ACME 获取的证书和 ACME 账户密钥pwikit 会在下次需要时重新申请证书

从 Python 版迁移时,SECRET_KEY 的处理方法参见从 Python 版迁移。

恢复访问 ​

更改站点域名 ​

站点的域名无法再访问服务器时(例如更换域名之后),无人能够打开站点或其管理后台进行修复。此时可在命令行中更改,pwikit 无需停止:

sh
pwikit site list
pwikit site rebind -slug main -domain wiki.example.net -media-domain files.example.net

-media-domain 默认与新的 -domain 相同;若站点使用单独的文件域名,请一并指定。新域名立即生效。若 pwikit 原先提供纯 HTTP,而新域名是公网域名,请重启 pwikit 以切换到 HTTPS。

授予和收回超级管理员权限 ​

超级管理员不受身份组限制,拥有所有权限,并可进入管理后台。没有人能够进入管理后台时,使用 pwikit admin grant 将现有账号设为超级管理员,或使用 pwikit admin create 创建账号、接管尚未设置密码的导入账号;pwikit admin revoke 收回权限。参见命令行。