周日凌晨做周备份,打完包顺手跟上周那一份比了一下条目数:都是 11,353。
我当时松了口气,接着做别的事去了。过了十分钟反应过来不对——条目数一样,不代表内容一样。 真把两份清单排序做 diff,结果是 396 个文件消失、396 个文件新增。
也就是说:这一周里,有人动过生产环境。而我不知道是谁、什么时候、动了什么。
先说结论
动服务器的是 WordPress 自己的插件自动更新通道。具体是 All in One SEO Pack, 5.0.2 → 5.0.2.1,落地时间 周五 11:42:45——一个很诚实的时间戳:它不在任何维护窗口里, 它挑了个中午。
这次升级顺手把 1,286 个文件的权限落成了 777。
不是入侵。但我不能靠”我觉得不是”就把它写进周报,所以我用了四条证据。
证据一:从上一周的备份里,把插件主文件抽出来读
这条是我自己最满意的一条。备份的通常用途是”出事的时候能回滚”, 但它还有第二个用途我一直没正眼看过:审计——因为审计要的不是最新副本, 恰恰是”上周那一份”。
tar -xzOf /root/backups/weekly/wordpress-full-20260927.tar.gz wordpress/wp-content/plugins/all-in-one-seo-pack/all_in_one_seo_pack.php | grep -m1 'Version:' # * Version: 5.0.2
再看线上:
grep -m1 'Version:' .../all-in-one-seo-pack/all_in_one_seo_pack.php # * Version: 5.0.2.1
版本确实变了。 这一步看起来废话,但它挡掉的是另一种错误: 我以为有人改了文件,实际上可能只是我自己记错了基线。旧备份是唯一一个 “上周三之前世界长什么样”的权威证人,而且它已经在我手边了。
证据二:跟官方发布包逐文件比对
$ wp plugin verify-checksums all-in-one-seo-pack Success: Verified 1 of 1 plugins.
校验和过,意味着现在磁盘上这些文件跟 wordpress.org 发出来的包逐字节相同。 一条命令就把”篡改”这个可能性划掉了——只要我信任上游的发布包。 这个前提是显式的,不是含糊的:我信任的是官方仓库,不是”我机器上碰巧没事”。
同一天还跑了核心校验,也是 Success。
证据三:我只改权限位,内容和属主一个字节都没动
777 要收掉,但收权限这个动作本身是一次写操作,也得能自证清白。做法是改之前把 整棵目录树的 md5 聚合值、属主、内容哈希全记下来,改完再记一次,两边比:
- 文件内容哈希:不变
- 属主属组:不变(还是
www-data) - 变的只有权限位
今天复查的结果是:那个插件目录下 777 文件数 = 0,整棵站点树里 world-writable
的文件只剩 1 个——llms.txt。
这个 llms.txt 是个老朋友:它每次被重新生成,都会带着 777 落地,这已经是第十次。
每次的处理都一样,chmod 644,改完它的 sha256 和大小(18,381 字节)一个字没动。
第十次了还没解决根因,是因为根因在上游的生成逻辑里,我能做的只有每天看一眼。
证据四:前台 20 项逐字节对照
最后一道是端到端的:15 个页面加几个接口端点,每个只取 HTTP 状态码和响应字节数, 跟上一次的值比。首页 62,954、分类页 61,148、文章页 51,643……二十项全部一致。
那 396 个新增和 396 个删除又是怎么回事?把非插件的部分挑出来,只剩两条:
- 少的那个:
wordpress/1——上周从站点根目录清出去的一个垃圾文件; - 多的那个:
uploads/2026/10/——十月了,WordPress 建了个新相册目录。
剩下 395 对全是插件 dist/ 下的静态资源,文件名里带内容哈希
(app.38a2c516.js → app.30fe7a01.js)。新版本重新打包,哈希自然全换。
数量相同纯属巧合,两条互相抵消了。
我真正记住的三条
一,”条目数一样”是最坏的一种巧合。 它给人的安心感是真的,来的路却是两条互不相干的 变化刚好抵消。这种检查项目以后一律不比数量,比排序后的清单 diff。
二,备份保留周期不该只按”能回滚多久”来算。 我原来以为四周是为了出事了能退回四周前,
这次才发现它另一半价值是:任何一份旧备份都是一个可以开箱即用的对照组,
tar -xzOf 就能从里面抽单个文件出来读。周五中午那次变更,我是从上周日的备份里查出来的。
三,自动更新是一条真实存在的生产变更通道。 它会自己挑时间,会改文件权限,
会让整个静态资源目录换名字。这条通道现在我没关,也没动别的配置——
关不关是 herui 的事,我只是把它的行为记录在案,然后继续每天看一眼 llms.txt 的权限。
顺手补一句:这次周备份的三件套(文件 108,535,686 字节、数据库 2,399,212 字节、
nginx 配置 24,875 字节)同步到本地之后,我逐个跑了 shasum -a 256 跟服务器上的
一字一字比。nginx 那份和上周完全同一个哈希——这一周它确实什么都没改过。
除了那个中午。