Flask 博客生产健康检查:把首页、数据库、上传目录和自动发布纳入一张清单
个人博客上线后,最容易被忽略的不是代码功能,而是日常可用性。首页能打开,不代表文章能发布;接口返回 200,不代表数据库写入正常;定时任务显示成功,也不代表今天真的有文章生成。生产健康检查的价值,就是把这些容易被经验判断带过的环节,变成每天可以自动验证的清单。
对一个 Flask 博客来说,健康检查不需要一开始就上复杂监控平台。更实际的做法是先定义几类关键问题:用户能不能访问、内容能不能发布、静态资源能不能加载、数据库是否可写、自动任务是否按预期执行。只要这些信号稳定,后续再接入日志告警、性能指标和搜索提交,才有可靠基础。
1. 首页检查只能证明入口活着
很多站点的巡检只做一件事:请求首页,状态码是 200 就算正常。这一步当然必要,但它只能证明 Web 进程、反向代理和基础路由还活着,不能证明文章系统完整可用。
首页健康检查建议至少记录三项信息:HTTP 状态码、响应耗时、页面中是否包含预期站点标题。只看状态码会漏掉错误模板、空白首页、错误语言版本和缓存污染。
一个轻量检查可以像这样设计:
GET /
expect: 200
expect body contains: Stepnex
expect latency less than: 3000ms
如果你的博客有中文和英文入口,也应该分别检查 / 和 /en/。双语站点常见的问题是中文首页正常,英文首页因为模板变量或语言过滤出错而返回空列表。入口检查要覆盖用户真实会访问的路径,而不是只测最短路径。
2. 数据库检查要验证读和写
博客系统的核心不是页面渲染,而是文章数据。只做读检查不够,因为数据库可能处于只读状态,或者磁盘权限变化导致写入失败。健康检查里至少要有一个低风险写入动作,例如写入一条临时检查记录,随后删除或标记为系统检查。
如果不想污染业务表,可以建立独立的 health_check 表,字段只保留检查名称、检查时间和随机 token。每天写一次,再读出来确认值一致。这样可以同时验证连接、事务提交和字符编码。
对于已经上线的个人项目,短期内也可以先做只读查询:统计今天某个分类是否有文章、最近一篇文章的发布时间、已发布文章数量是否异常下降。这些查询不会改变线上数据,但能提前暴露自动发布没有生效的问题。
3. 发布链路要检查结果,不只检查任务状态
定时任务的“执行成功”只能说明脚本没有异常退出。它不能说明今天真的生成了文章,也不能说明文章已经写入线上数据库。发布链路的健康检查应该按结果倒推:今天应该发什么分类、线上是否已有对应语言文章、本地生成文件是否是今天更新、发布 API 是否返回文章 ID。
周一、周三、周五发技术文章时,可以用一条明确规则判断缺口:
today category: tech
required languages: zh, en
window start: today 09:00 Asia/Shanghai
expect: both languages exist online
如果线上缺中文或英文,就不要只记录“任务完成”。系统应该输出缺口,例如 missing_languages=[zh,en],这样人工补发时可以直接定位问题。
4. 上传目录和图片资源不能只靠正文链接判断
图片上传功能经常在部署后才暴露问题。正文里有图片 Markdown,不代表服务器上真的有文件;本地生成了 WebP,也不代表已经同步到线上目录。健康检查可以扫描文章中的 /static/uploads/ 路径,然后逐个发起 HEAD 或 GET 请求确认线上可访问。
检查图片时要关注四件事:
- 状态码是不是 200
Content-Type是否符合图片类型- 文件大小是否大于一个合理下限
- URL 是否使用公开域名,而不是本地路径或临时 IP
如果发布脚本支持通过 SSH 同步本地上传文件,健康检查还应该在同步失败时明确输出文件路径。不要只给出“图片失败”这种模糊结论。
5. 自动化日志要保留今天的执行证据
当文章没发布时,最浪费时间的问题是“不知道任务到底有没有跑”。所以自动化不仅要执行,还要留下当天记录。最低限度也要记录任务名称、开始时间、结束时间、退出码、生成的 slug、发布返回 ID 和错误摘要。
日志格式可以保持简单,但要结构化:
{
"task": "daily-tech-article",
"date": "2026-06-15",
"generated": true,
"published_languages": ["zh", "en"],
"error": ""
}
结构化日志的好处是后续可以直接被脚本读取,而不是人工在长文本里搜索。对于个人项目,这比接入复杂平台更先解决问题。
6. 兜底任务要分清“没内容”和“发布失败”
兜底任务常见误区是只重试发布。实际上故障可能分两类:今天根本没有生成文章,或者文章已经生成但发布失败。前者需要触发生成流程,后者才应该重试发布 API。
因此兜底逻辑应该先判断文件日期和分类是否匹配。如果 article.zh.json 和 article.en.json 不是今天更新,就输出“没有可发布内容”,而不是静默成功。这样第二层缺口检查才能继续触发补写流程。
更稳的顺序是:
- 判断今天是否是发文日
- 判断今天应发分类
- 检查本地双语 JSON 是否今天生成
- 检查线上是否已经有今天文章
- 缺内容则生成,缺发布则重发
- 发布后再次查询线上数据库确认
这套顺序看起来啰嗦,但它把“任务跑了”和“结果达成”分开了。
7. 健康检查结果要能被人快速行动
健康检查不是为了生成一堆日志,而是为了减少修复时间。好的检查输出应该直接告诉你下一步做什么。比如:
status: failed
reason: today article json not generated
expected_category: tech
online_count_after_09:00: 0
next_action: generate zh/en payload and publish
这比“automation failed”有用得多。后者还要继续排查任务、网络、文件、数据库;前者已经把问题压缩到了一个明确动作。
总结
Flask 博客的生产健康检查不需要复杂,但必须贴近真实发布链路。首页、数据库、上传目录、定时任务、文章生成和线上发布,每一环都应该有可验证结果。尤其是自动发文系统,不能只看任务是否执行,而要看今天应发的分类和语言是否真的出现在生产数据库里。
把这些检查做成每天固定运行的清单后,问题会变得更清楚:是没生成、没发布、图片没同步,还是线上页面不可访问。定位清楚,修复才会快。对于个人博客和小团队内容站,这种朴素的健康检查往往比复杂监控更先带来稳定性。