今天踩了一个让我后背发凉的坑。
说到这个,我差点把整个生产环境搞崩了。
第一个坑:我写了个版本切换功能,就一行代码的事儿——用户选个 v3 或 v4,改个内存里的 _config,然后用 yaml.safe_dump 写回 config.yml。
看着挺顺的,对吧?
其实根本没考虑过一件事:_config 是什么时候加载的?
回到正题,问题出在这儿:
app.py 启动时会执行 _config = load_config()。
如果上次服务器重启前 config.yml 被写坏了(比如被某个脚本误删了部分),那这次加载进来的 _config 就只剩两行:workflow_version 和 dashboard。
这时候你再 dump 回去?
整个 config.yml 直接被替换成一个“空壳”,accounts、tencent_cloud、platforms 全没了。
所有公众号的 app_id 和 app_secret 都丢了!
更糟的是我还写了自动备份逻辑:
shutil.copy2(config_path, backup_path)
但这个备份是基于已经被污染的 config.yml 创建的。
所以备份文件也是坏的,根本没法用。
后果是什么?
一键发布功能彻底挂了。
wechat_markdown_uploader.py 报错说:“请设置 WECHAT_APP_ID 和 WECHAT_APP_SECRET 环境变量”——其实不是环境变量的问题,是配置文件里压根就没有这些字段。
腾讯云内容安全检测也瘫了,因为 tencent_cloud 配置没了。
所有平台适配器的配置也没了,整个系统跑不动了。
排查花了将近半小时。
我先看 config.yml,发现只有两行;
又去看备份,发现备份也是坏的;
最后回忆最近操作,才意识到是版本切换 API 引起的。
恢复过程倒是快:
突然想起外置 SSD 上有个项目备份 /Volumes/jf01/AppData/hermes/skills/media/jianfei-wechat/config.yml。
跑去一看,居然完整!马上复制回来,一切恢复正常。
修复方案也很简单:
写入 config.yml 前,先重新读取完整配置,再只改目标字段,最后写回。
这样即使内存中的 _config 不完整,也不会影响最终结果。
备份逻辑改成直接从磁盘文件拷贝,而不是依赖内存副本。
不然备份和原文件就是同一个烂版本。
写完还要验证一下:确保关键字段(比如 accounts、tencent_cloud)都在,不能只靠“看起来没问题”。
这次教训很深刻:
永远别拿内存里的配置直接覆盖整个文件。
它可能是残缺的、过期的、甚至被篡改过的。
备份必须基于磁盘上的原始文件,不是内存中的副本。
否则你备份的是个“假货”。
修改配置文件的操作,要像数据库 UPDATE 一样——只改需要的字段,别重写整张表。
这才是安全的做法。
生产环境的任何配置改动,都得有版本控制和回滚机制。
哪怕只是一个简单的 YAML 文件。