# 日常维护与故障排查 本文档记录正式看板的运行基线、常用诊断方法和已确认故障。接口路径、监听端口、Python 环境、启动脚本、systemd 服务或部署流程发生变化时,必须同步更新本文档;出现新的线上或本地故障时,按日期追加记录,不覆盖历史结论。 ## 运行基线 | 项目 | 当前约定 | |---|---| | 本地正式看板端口 | `8080` | | 当前 API 前缀 | `/api/reading/*` | | 兼容 API 前缀 | `/api/v2/*`,仅用于旧客户端过渡 | | 项目 Python | 优先使用项目根目录 `.venv/bin/python` | | 服务器服务 | `weread.service`,端口以服务中的 `PORT` 为准 | | 服务器目录 | `/opt/weread-board/WeReadBoard` | 同一运行环境只保留一个正式服务实例。不要同时使用 `start_server.sh` 和 `start_dashboard.sh` 启动不同端口,否则静态文件、后端路由和 Python 环境可能来自不同进程,容易产生误判。历史静态 Demo 需要临时预览时可以单独启动,用完后应及时停止。 ## 快速排查 页面出现“请求失败”时,按下面的顺序检查。 ### 检查监听端口 本机: ```sh lsof -nP -iTCP -sTCP:LISTEN ``` 服务器: ```sh sudo ss -ltnp sudo systemctl status weread.service --no-pager ``` 确认正式服务只监听预期端口,并核对进程的启动时间与 Python 路径: ```sh ps -fp lsof -a -p -d cwd ``` ### 分层检查接口 本机设置了 HTTP 代理时,必须绕过代理访问本地地址: ```sh curl --noproxy '*' -i http://127.0.0.1:8080/ curl --noproxy '*' -i http://127.0.0.1:8080/api/reading/status curl --noproxy '*' -i 'http://127.0.0.1:8080/api/reading/shelf?tab=all&progress=0' curl --noproxy '*' -i 'http://127.0.0.1:8080/api/reading/dashboard?period=week' ``` - 页面返回 200、API 返回 404:运行中的后端没有加载当前路由,检查部署提交与服务重启。 - API 返回 502:路由已经加载,但数据库或微信读书上游调用失败,查看响应正文和服务日志。 - 请求一直等待:检查上游网络、DNS、TLS 证书和接口超时,不要只修改前端路径。 服务器日志: ```sh sudo journalctl -u weread.service -n 100 --no-pager ``` ## 2026-09-14:接口调整后页面请求失败 ### 现象 - `http://127.0.0.1:8080/` 可以打开,但页面显示“请求失败”。 - `/api/reading/shelf` 和 `/api/reading/dashboard` 返回 502。 - 旧的 `8770` 进程仍能通过 `/api/v2/status` 返回数据。 ### 根因 接口调整只修改了 Flask 路由名称和前端请求前缀,微信读书 HTTPS 请求逻辑没有变化。真正差异来自服务重启后选择了另一套 Python: - 旧 `8770` 进程使用 WorkBuddy Python,其默认 CA 文件为 `/private/etc/ssl/cert.pem`。 - 新 `8080` 进程因项目没有 `.venv`,由 `start_server.sh` 选择系统 Python。 - 该系统 Python 的默认 CA 文件为空,访问 `https://i.weread.qq.com` 时出现 `CERTIFICATE_VERIFY_FAILED`。 完整因果链路如下: ```text 接口调整需要重启服务 -> 启动脚本选择了不同的 Python -> 新 Python 无法找到 CA 证书 -> 微信读书 HTTPS 请求失败 -> 聚合接口返回 502 -> 前端显示“请求失败” ``` 因此,接口调整是触发条件,不是 HTTPS 故障本身。兼容路径只能处理旧进程返回 404 的过渡状态;同一后端因上游 TLS 失败而返回 502 时,切换 `/api/reading/*` 或 `/api/v2/*` 都不能解决问题。 ### 诊断证据 检查 Python 与默认 CA 文件: ```sh python3 -c "import sys, ssl; print(sys.executable); print(ssl.get_default_verify_paths())" ``` 故障环境中,`cafile` 为 `None`,且 Python 预期的证书文件不存在。系统证书 `/etc/ssl/cert.pem` 可用,使用它重新启动后,状态、书架和概览接口均恢复为 200。 ### 恢复方式 本机临时恢复: ```sh SSL_CERT_FILE=/etc/ssl/cert.pem PORT=8080 python3 app.py ``` 服务器由 systemd 管理时,先确认服务器证书文件的实际路径;仅在 Python 默认 CA 路径缺失时,为 `weread.service` 配置 `SSL_CERT_FILE`,然后执行: ```sh sudo systemctl daemon-reload sudo systemctl restart weread.service ``` 不要关闭 TLS 校验,也不要在代码中使用不验证证书的 SSL Context。 ### 预防与验收 1. 部署和本地启动统一使用项目 `.venv/bin/python`,不要让不同启动脚本静默选择不同解释器。 2. 重启前检查 Python 的 `ssl.get_default_verify_paths()`,确认 CA 文件存在且可读。 3. 每次只保留一个正式服务端口,停止旧实例后再验收新实例。 4. 接口、端口、Python 环境、启动脚本、systemd 配置或部署方式变化时,同步更新本文档的“运行基线”和相关故障记录。 5. 验收必须同时检查页面、`status`、`shelf` 和 `dashboard`,不能只确认首页返回 200。 本次本地恢复后的验收结果:正式服务仅监听 `8080`,页面及上述三个 API 均返回 200;旧 `8770` 实例和 `8766` 静态预览均已停止。 ## 故障记录模板 新增故障时使用以下结构: ```markdown ## YYYY-MM-DD:故障标题 ### 现象 ### 根因 ### 诊断证据 ### 恢复方式 ### 预防与验收 ```