一个人维护几个站,最贵的成本不是钱,是注意力。服务器出问题的时候,真正浪费时间的地方在于:你得先回忆这台机器上到底跑了什么、配置文件在哪、上次改了什么、数据库密码存在哪儿,然后才开始排查。前面这二十分钟的"回忆",一天能遇到三四次,一年就是几百个小时。
这篇写我从"凭记忆维护"到"靠一份清单维护"的转变。这套东西一共六张表,加起来不到五百行文字,全部放在一个 Git 仓库里,改一次提交一次。它不是运维 wiki,也不是文档系统,就是我自己给自己写的备忘录,只不过写成了能在紧急情况下被人(包括三个月后的我自己)照着执行的形式。
一、先想清楚这六张表解决什么问题
写台账最怕的是"为了记录而记录",最后变成一堆没人看的表格。所以每张表必须对应一个具体的、会真实发生的痛点。我列的六个痛点是:
- 换机器 / 加机器时:忘了这台机器上有哪些站点、哪些 cron、哪些证书,靠回忆必定漏。
- 半夜被叫醒时:脑子不清醒,需要一份"从哪开始查"的固定顺序,不能每次都重新想。
- 改配置之前:不知道这个参数当初为什么这么写,容易改掉一个有理由的设置。
- 续费与证书到期:域名、服务器、证书三条时间线,纯靠脑子记一定会出事故。
- 交接 / 授权:偶尔要把某个站临时交给别人处理,得能快速说清"动哪里会有什么后果"。
- 复盘:半年后想知道"这次故障以前是不是发生过",需要有一份带日期的故障记录。
对应这六点,六张表就是:资产表、站点表、变更记录、故障记录、到期日历、检查单。下面逐个说内容结构和写法。
二、资产表:一行一台机器,只写"会变的东西"
资产表最容易写成参数大全(CPU 几核、内存多少、硬盘多大),但这些参数三个月后就没人看了,而且服务商控制台里一眼能看到。真正有价值的是控制台里看不到的东西:系统版本、SSH 端口、登录方式、key 的位置、防火墙规则在哪儿、备份落在哪儿。
## 资产表
| 名称 | IP / 端口 | 用途 | 系统 | SSH | 面板 | 备份去向 | 备注 |
|------|-----------|------|------|-----|------|----------|------|
| vp1 | 1.2.3.4:22 | 主站 + 数据库 | Debian 12 | key only | 无 | 每日 03:20 到对象存储 A | 磁盘 90% 时要清 thumbs |
| vp2 | 5.6.7.8:50973 | 跳板 + DNS | Debian 11 | key + 2FA | 无 | 每周全量到本地 | 只允许 vp1 连入 |
| hk1 | 9.9.9.9:2222 | 静态站 + CDN 源 | Ubuntu 22.04 | key only | 无 | 每周 rsync 到 vp2 | Cloudflare 回源只认它 |几个写法上的原则:
- SSH 端口一定要写。改过默认端口的机器,下次换电脑没带笔记就抓瞎。
- "备份去向"要写具体到路径或桶名,不写"云备份"这种。出事的时候你要能直接
ssh过去ls。 - 备注列写"这个机器的雷",而不是写"运行良好"。比如"磁盘 90% 要清 thumbs"就是我三次踩坑之后写的,它的价值远高于任何硬件参数。
- 不要写密码。表的用途是索引,不是保险箱。密码走密码管理器,表里只写"密码在 1Password 的 xxx 条目"。
三、站点表:一个站一行,把"依赖关系"写出来
站点表是六张表里价值最高的一张。它的核心作用是把一个站拆成"域名 → 服务器 → 目录 → 数据库 → 缓存 → 证书"这条完整链路,让人能一眼看出改一处会牵动哪儿。
## 站点表
### www.example.com
- 服务器:vp1
- 根目录:/www/example.com
- 程序:Typecho 1.2 / PHP 8.1 / MySQL 8.0
- 数据库:example_db(账号在密码管理器)
- 缓存:Nginx fastcgi_cache,目录 /var/cache/nginx/example
- 证书:Let's Encrypt,webroot 验证,续期 timer 已开
- CDN:Cloudflare,代理开启,缓存规则见下
- 特殊配置:/etc/nginx/conf.d/example.conf 里有一段城市级 301
- 改之前必看:这个站有自定义伪静态,改 permalink 会影响 2000+ 条已收录 URL"改之前必看"这一行是整张表的灵魂。它记录的是不可从代码里读出来的约束——为什么不能动、动了会怎样。举个真实例子:某站的手动 301 规则里有 40 条,原因是旧版 URL 被搜索引擎收录过,一旦删掉这 40 条,权重就断了。这个信息在任何配置文件里都看不出来,只有台账能记。
站点表还有一个实用价值:新加站点时照着抄一遍,能发现漏项。因为字段是固定的,每次都要填"证书怎么续"、"缓存怎么清"、"备份在哪",想漏也漏不掉。我自己就靠这张表发现过两个站没配自动续期。
四、变更记录:只记"改了什么 + 为什么 + 怎么回滚"
变更记录不需要写成流水账。真正有用的只有三样东西:时间、改了什么、回滚方式。至于"为什么改"写一句就够,重点是那句"为什么"要在半年后仍然看得懂。
## 变更记录
### 2026-11-02 14:30 vp1
- 改:nginx.conf 的 worker_connections 1024 -> 4096
- 因:晚高峰出现 "worker_connections are not enough"
- 回滚:git checkout HEAD~1 nginx.conf && nginx -t && systemctl reload nginx
- 验证:24 小时内该 warn 未再出现
### 2026-10-28 21:10 vp1
- 改:MySQL innodb_buffer_pool_size 512M -> 1G
- 因:Buffer pool hit rate 长期 96%,想压到 99%
- 回滚:改回 my.cnf 重启 mysqld(注意:重启约 20 秒不可用)
- 验证:次日 hit rate 99.3%,QPS 无变化两个细节值得坚持。第一,回滚命令要能直接复制粘贴,不要写"改回去"这种。第二,记下"验证方式",否则下次看到同样的改动,你不知道它到底有没有用,可能会重复试错。
如果配置本来就在 Git 里管,变更记录可以只写一行指过去("见 commit abc1234")。但有些改动在 Git 外面,比如数据库参数、面板里点的按钮、服务商后台改的 DNS,这些必须手写进来。
五、故障记录:写"症状 + 根因 + 下次怎么更快"
故障记录是唯一能让排查能力随时间变强的表。它不求完整,求的是下一次同类问题上能省时间。我的模板是这样的:
## 故障记录
### 2026-11-05 03:40 vp1 影响 12 分钟
- 症状:全站 502,Nginx error log 大量 "connect() to unix:/run/php/php8.1-fpm.sock failed"
- 直接原因:php-fpm 进程池打满,max_children 设为 10,实际并发 40+
- 根因:某采集插件每分钟跑一次全量抓取,慢查询堆积
- 处置:临时把 max_children 调到 30,禁用该插件 cron
- 下次更快:先 curl 本机 127.0.0.1:80 看是否 502,是的话直接看 fpm slowlog,别先看应用日志
- 遗留:该插件的全量抓取改为增量,TODO 在站点表里"下次更快"这一行是重点。故障记录的价值不在于记录事故本身,而在于把排查路径固化下来。积累十几条之后,你会发现很多故障的入口是同一个:502 先看 fpm、503 先看 upstream、504 先看后端响应时间。这些经验写在文档里,比记在脑子里可靠。
另外,故障记录里要写影响时长。这个数字既是对自己的提醒,也是评估"要不要为这个问题做架构改动"的依据。影响 2 分钟的故障不值得上高可用,影响 2 小时的必须改。
六、到期日历:三条时间线,一个文件
域名、服务器、证书是三条独立的到期线,任何一条断了都会造成真实损失:域名过期会被抢注,服务器过期会直接停机,证书过期会让全站变成不安全警告。这三条线用脑子记一定会漏,必须落成文件 + 提醒。
## 到期日历
| 项目 | 到期日 | 续费方式 | 提前量 |
|------|--------|----------|--------|
| example.com 域名 | 2027-03-15 | 服务商后台,手动 | 60 天 |
| vp1 服务器 | 2027-01-08 | 按月自动扣款 | 30 天核对卡 |
| hk1 服务器 | 2026-12-20 | 手动续,不支持自动 | 45 天 |
| *.example.com 证书 | 自动 | certbot timer | 30 天检查一次 |
| 对象存储套餐 | 2027-06-01 | 手动 | 30 天 |配合一个每天跑的任务,读这份表算剩余天数,小于提前量就发通知。这样"到期"这件事就完全不需要占用注意力了。注意表里要区分自动续费和手动续费,手动的那几项才是真正的风险点。
七、检查单:把重复的判断变成可执行的步骤
检查单分两种,一种日常,一种应急。它们的形式完全不同,不要混。
日常检查单是给空闲时间用的,目的是发现缓慢恶化的问题,比如磁盘逐渐变满、证书快到期、备份连续失败。每周固定十几分钟跑一遍:
## 每周检查(15 分钟)
- [ ] df -h / df -i 各分区,低于 85%
- [ ] 备份任务最近 3 次是否成功(看日志尾部和文件大小)
- [ ] 证书剩余天数(>20 天)
- [ ] MySQL 主从 / 复制延迟(如有)
- [ ] Nginx 5xx 比例(对比上周)
- [ ] 到期日历 30 天内项目
- [ ] 磁盘 IO 与负载曲线(有没有异常抬升)应急检查单是给慌乱状态用的,必须写成"照着敲"的形式,每条命令都能直接执行,不用现场思考参数:
## 应急:全站打不开
1. 本机是否活着
curl -sS -o /dev/null -w "%{http_code} %{time_total}\n" http://127.0.0.1/
2. Nginx 是否在跑
systemctl is-active nginx; nginx -t
3. 后端是否在跑
systemctl is-active php8.1-fpm; ss -lntp | grep -E "9000|3306"
4. 磁盘是否满
df -h /; df -i /
5. 最近 50 条错误
tail -50 /var/log/nginx/error.log
6. 最近改了什么
cd /www/conf && git log --oneline -5应急检查单的关键是顺序——从外到内,从最可能到最不可能。把人最容易忘的"最近改了什么"放在最后一条,是因为十次里有七次事故是最近一次改动引起的,但人在慌乱时最先忘的就是查这个。
八、放在哪、怎么维护才不烂尾
文档烂尾的唯一原因是维护成本太高。所以我的做法是三条硬规矩:
- 全部放在一个 Git 仓库里,六个文件(或者一个文件分六节),改一次提交一次。提交信息就是变更记录,两者不重复劳动。
- 只写会变的和查不到的。CPU 核数、内存大小、软件版本号能自动查到的,一律不写。这一条让台账的体积控制在一屏能翻完的范围内。
- 每次事故后必须补三处:资产表的备注(这个机器的雷)、故障记录(症状和下次怎么查)、应急检查单(把这次有效的命令加进去)。这是唯一的强制更新点,其余时间可以不动。
关于格式,不必追求工具。Markdown + Git 就够了,真要检索可以用 grep。我一开始试过各种文档系统,最后都因为"打开成本太高"而废弃。一个能 cat 出来的文件,才是真会被用的文件。
如果担心文件泄露(里面有 IP 和路径),把仓库设成私有,或者干脆放在本机的一个磁盘外目录。它不需要同步到任何地方,因为它的读者只有你自己。
九、半年之后的变化
这套东西我用了大半年,最明显的变化不是"少出事故",而是每次事故的处置时间变短了。因为排查路径被固化成检查单,不需要现场推理;因为资产表和站点表写清了依赖,改动之前就知道会牵动什么;因为变更记录写了回滚命令,敢在半夜直接动手而不是等到天亮。
还有一个意外收获:写台账的过程本身就是一次审计。我在填站点表的时候发现有两个站的数据库账号是同一个、密码还很弱;填终表的时候发现三个域名挂在同一个即将涨价的注册商下。这些问题如果不去填表,大概永远不会被注意到。
最后说一句我的看法:一个人维护站点,规模的天花板不在服务器性能,而在"你脑子里能同时记住多少细节"。台账的作用就是把这些细节从脑子里搬到磁盘上,把可维护的规模从两三个站提到十来个站。它花的半天时间,是这几年我投入产出比最高的一笔。