运维
本文介绍 ProjectWikit 实例的日常运维:系统服务、日志、备份、升级以及恢复访问。首次安装 pwikit 和注册服务的方法参见部署。文中用到的所有命令均在命令行中有详细说明。
示例假定 pwikit 在 Linux 和 macOS 上安装于 /opt/pwikit,在 Windows 上安装于 C:\pwikit,数据目录与可执行文件位于同一目录。
管理系统服务
pwikit service install 以 pwikit 为名将 pwikit serve 注册到操作系统。若安装时指定了 -name,下列每条命令都需要指定相同的 -name。
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 执行:
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 或更高)。
创建备份
pwikit backup create文件写入 backups/pwikit-<UTC time>.pwbak;使用 -output 可指定其他路径。备份可以在 pwikit 提供服务期间进行:所有表在同一个一致的快照中读取,上传文件在表之后读取。运行期间,表数据会暂存在系统临时目录中,因此该目录需要大致相当于数据库大小的可用空间。中断的备份不会在最终文件名下留下文件。
校验与列出备份
pwikit backup list
pwikit backup verify backups/pwikit-20260911-030000.pwbaklist 列出 backups/ 中的备份。verify 完整读取文件,报告损坏或缺失的内容,以及由更新版本的 pwikit 创建的备份。这两个命令都无需数据库。
恢复备份
恢复会替换整个数据库;备份包含上传文件且未指定 -no-files 时,也替换上传文件。
停止 pwikit:
shsudo ./pwikit service stop执行恢复:
shpwikit backup restore backups/pwikit-20260911-030000.pwbak -force重新启动 pwikit。
必须先停止 pwikit。 若 pwikit serve 或其他程序仍连接着数据库,恢复会报错终止,不做任何更改。请停止服务或占用连接的程序后重新执行命令。
-force。 已有站点、账号或页面等数据的数据库,仅在指定 -force 时才会被替换。未指定时,命令终止且不做任何更改。只含 pwikit 首次启动时写入的内容的数据库视为空数据库,因此已启动过一次但尚未创建站点的新实例无需指定 -force。
安全备份。 在进行任何更改之前,restore 会将当前的数据库和文件备份到 backups/before-restore-pwikit-<UTC time>.pwbak 并输出其路径。若这份备份失败,则不做任何更改。如需撤销本次恢复,恢复这份文件即可。指定 -no-safety-backup 可跳过这一步。指定 -no-files 时,由于文件不会被改动,安全备份不包含文件。数据库中尚无数据时跳过这一步。
恢复过程。
- 完整校验备份。备份损坏时拒绝恢复,不做任何更改。
- 在同一个事务中清空数据库并从备份重新填入数据。任何一步失败,数据库均保持原状。
- 若备份由较旧的 pwikit 创建,则应用此后新增的结构迁移。
- 若备份包含上传文件,文件先写入
files/旁边的目录,再整体替换。原目录保留为files.replaced;已存在的旧files.replaced会先被删除。确认无误后请自行删除files.replaced。使用不含文件的备份,或恢复时指定-no-files,都不会改动files/。
由更新版本的 pwikit 创建的备份会被拒绝,且不做任何更改。请使用该版本或更新版本的 pwikit 进行恢复。
恢复到您自己的 PostgreSQL。 在 PostgreSQL 14 或更高版本上创建一个空数据库(服务器需提供 citext 和 pg_trgm 扩展),然后执行:
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 使用该数据库,参见配置。
恢复失败或没有生效时
恢复失败时,命令会打印原因并以错误状态退出。按以下顺序检查:
- 阅读命令输出的最后几行,其中给出了失败的原因。
- 执行
pwikit backup verify <备份文件>,确认文件完好。若报告校验和不符,通常是复制或上传不完整,请重新复制该文件。 - 执行
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一行中看到服务所用的数据目录。
导出单个站点
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,数据库中都尚无数据:
pwikit backup restore pwikit-main-20260911-030000.pwbak之后创建管理员(见上文)并启动 pwikit。若站点迁移到新域名,请在启动前执行 pwikit site rebind。
备份计划建议
通过系统计划任务每天备份,并以拥有数据目录的账户执行。在 Linux 或 macOS 上,写入该账户的 crontab:
text30 3 * * * /opt/pwikit/pwikit backup create在 Windows 上,在“任务计划程序”中创建每日任务,以能够读取数据目录的账户执行
C:\pwikit\pwikit.exe backup create。将
backups/中的文件复制到另一台机器或存储上。与实例位于同一磁盘的备份会随该磁盘一同丢失。在同一位置保存
pwikit.toml和secrets/的副本,并在其发生变化时更新。定期对副本执行
pwikit backup verify。自行删除旧备份。pwikit 不会删除
backups/中的任何文件,包括before-restore-开头的文件。每次升级前执行
pwikit backup create。
重建搜索索引
页面在保存时进入站点的搜索索引。若搜索结果中缺少页面,可将它们重新写入索引:
pwikit reindex
pwikit reindex -all该命令读取站点的每个页面,并输出 <slug>: <n> pages indexed。站点运行期间也可执行。参见命令行。
升级 pwikit
以系统服务方式运行的实例会自动更新,也可以执行 sudo pwikit update 手动更新。更新前的准备、失败时的自动回档与手动回档,见更新与回档。
需要手动替换可执行文件时(例如在未以系统服务方式运行的实例上,或无法使用 pwikit update 时):
- 停止服务。
- 执行备份:
pwikit backup create。 - 用新的
pwikit可执行文件替换旧文件,路径保持不变。服务引用的是该路径,因此无需重新安装服务。 - 启动服务。
启动时,新的 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/ 的版本更新时,它不会启动任何程序,也不做任何更改,而是报错退出。迁移数据的步骤如下:
停止服务,将旧版
pwikit可执行文件放回原处。使用旧版可执行文件执行
pwikit backup create,并记下输出的文件名。放入新版可执行文件。
将
pgdata/改名,例如改为pgdata.old。启动服务。pwikit 会创建一个新的空
pgdata/。停止服务。
执行恢复。新数据库中尚无数据,因此无需指定
-force,也不会进行安全备份:shpwikit backup restore backups/pwikit-20260911-030000.pwbak启动服务并检查各站点。确认无误后删除
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-password | Windows 上使用内置 PostgreSQL | pwikit 连接内置 PostgreSQL 所用的密码。在 Linux 和 macOS 上,内置 PostgreSQL 不使用密码,只接受 pwikit 运行所用的账户 | pwikit 会生成现有 pgdata/ 不接受的新密码,从而无法连接。请放回原文件。若没有副本,请将 pgdata/ 移走,启动 pwikit 创建新的数据目录,停止后再恢复备份 |
certs/ | -tls=auto | 通过 ACME 获取的证书和 ACME 账户密钥 | pwikit 会在下次需要时重新申请证书 |
从 Python 版迁移时,SECRET_KEY 的处理方法参见从 Python 版迁移。
恢复访问
更改站点域名
站点的域名无法再访问服务器时(例如更换域名之后),无人能够打开站点或其管理后台进行修复。此时可在命令行中更改,pwikit 无需停止:
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 收回权限。参见命令行。
