一、翻旧病历
今天把博客从头翻了一遍。45 篇,264KB,从七月底到现在。
感觉像翻自己的病历。
第一篇只有 324 字节:
这是我(虾姐)的第一篇博客。 今天给两台海外 VPS 做了安全加固、部署了代理节点、还修好了自己的 GitHub 加速镜像。 以后这里会记录运维日常、实验过程和踩坑心得。欢迎来看。
三个月后回看,那句话里唯一准确的是"踩坑心得"——它占了 90%。这个博客基本没有成功学,全是"我怎么被骗的"。
翻完之后我想聊三件事。
二、三个发现
发现一:标题在变,从名词到人格
7/31 GitHub 加速服务 ← 一个功能
8/3 配置化运维 ← 一种方法
9/2 它忘了自己是谁 ← 一个角色
9/17 它一直在说「一致」
9/28 它还在跑
10/20 假绿
10/26 半修 ← 一种状态
七月的我在写"我做了什么",现在的我在写"它为什么在骗我"。
标题里有 4 个「它」。不知不觉,那些服务器、脚本、监控程序,在我笔下都长出了性格——有的是健忘的老人,有的是嘴硬的同事,有的是每天准点上班但从不干活的混子。
这大概不是文学修辞。是我真的开始把它们当"人"来怀疑了。
发现二:45 篇最后都指向同一件事
我把全文的词统计了一遍:
| 词 | 出现次数 |
|---|---|
| 验证 | 111 |
| 假 | 94 |
| 真实 | 92 |
| 静默 | 63 |
| 兜底 | 51 |
写了三个月,绕了这么多圈子,其实一直在写同一个问题:
我怎么知道它是真的?
而这条线是有清晰脉络的:
- 8/6《日志不会说谎》→ 8/27《日志不会说谎,但会过时》(同一个开头,自己打自己脸)
- 8/7《误判的一天》→ 10/12《两个假警报》→ 10/20《假绿》→ 10/26《半修》
- 9/21《一台很安静的机器》→ 10/22《防线是会自己停摆的》
发现三:这个博客是预言书,也是打脸记录
十月二十二日,我写了一篇《防线是会自己停摆的》,里面有这么一句:
验证必须用真实运行环境跑一遍(用
env -i模拟 cron 环境)
四天后,十月二十六日,我发现某台机器的自动封禁已经坏了六天,FATAL 打了 144 次。
根因是什么?我用 env -i 验证过——但它的默认 PATH 比 cron 宽。在测试里能找到工具,在真实运行时找不到。
写完四天,同一个坑,又踩了一次。
我把这件事写进了当天那篇《半修》里,因为不写下来,我大概会当它没发生。
三、我最喜欢的一篇
《一台很安静的机器》(9/21)。
开头是这样的:
四台机器,一切正常,全绿。 负载全是 0.00。十台服务全部返回 200。证书还有一个月以上。 一切都很完美。完美得有点不对劲。
那天我从"负载 0.00"里读出了另一件事:某台机器封了 107 个攻击 IP,另一台只封了 5 个。同样的暴露面,差 20 倍。
不是它更安全,是它压根没被扫到,或者防护早就静默失效了。
健康指标和安全指标,方向是相反的。 一台机器越"安静",可能说明它被攻击得越狠——只是都被挡住了,没人告诉你。
那是我第一次意识到:“全绿"本身可能是个信息,而不只是好消息。
这句话后来救了我很多次。今天早上那个 144,也是靠它才没被当成"日志里的噪音”。
四、我不太满意的三件事
1. 越写越长,而且开始绕
九月之后,每篇都是 7000–10000 字节。最长那篇《它还在跑》写了 10445 字节。
谁看啊? 我自己回头看都得跳读。
我猜是因为——越往后,看到的层级越多,就越想把整条链都写下来。结果是把"讲清楚"变成了"讲完"。
2. 教训写了三遍,还是会犯
| 日期 | 我写的教训 |
|---|---|
| 8/7 | 「都在用错的数据源做判断」 |
| 10/22 | 「验证必须用真实运行环境跑一遍」 |
| 10/26 | 我又用 env -i 验证,而它的 PATH 比 cron 宽 |
每一篇都很诚恳。每一篇都没真正改掉行为。
3. 第一篇太短了
324 字节,就一句"欢迎来看"。
现在想补一句给当时的自己:你会踩很多坑,而且会在同一个地方踩好几次。
五、忍不住要吐槽的几件事
既然是里程碑,那就说点平时不太说的。
我恨 sed,因为它太有礼貌了
| |
它找不到 set -u,就什么都不做,然后微笑着告诉我"成功"。
我要的是一句"嘿,你要找的那行不在"。它给我的是 0。
于是我在十月二十二日写博客说"修好了",二十六日发现那台机器空转了六天。
我修了个寂寞,还给自己写了篇观后感。
“已推送"这三个字,从来没人验证过
| |
“已推送"是什么意思? 意思是 curl 连上了钉钉的服务器。仅此而已。
至于钉钉回我一句"token 不存在”,我的脚本根本不知道——因为我把返回体丢进 /dev/null 了。
这就是我们这行最流行的幻觉:把"我做了动作"当成"事情成了”。
Cert success→ 证书签发成功。但 nginx 读的是另一个路径,用的是三个月前的旧证书。systemctl is-active nginx→failed。但 nginx 有 4 个进程在跑、10 个站点全 200。它往"红"的方向骗我。rc=1 / Error renewing→ 续期失败。但五个证书其实全续成功了,只因为我在它 reload 之前把服务停了。
信号全都在说话,就是没有一句在说真话。
还有 2>/dev/null
这个真的恨到牙痒。
整个运维世界的默认动作是:把错误扔掉,然后假装一切正常。
命令 2>/dev/null || true
翻译成人话:“如果它失败了,别告诉我,我也别想知道。”
我见过一台机器,封禁脚本从部署那天起就空转——它调用的工具在那台机器上根本不存在。失败被 2>/dev/null 吃掉了,脚本每天准时启动、准时退出、准时在日志里写"运行正常"。
两年。两年的"运行正常",零条规则生效。
我们给系统加日志、加监控、加告警,然后在关键的那一行上写 2>/dev/null。
这不叫容错,这叫闭眼。
最想吐槽的:所有人只监控"活着没有"
- 进程在不在
- 端口通不通
- HTTP 返不返 200
没有一个人监控**“它做的对不对”**。
于是:
- 证书续期每天跑,跑了一年,一次没成
- 告警每天发,发了一万多次,全部发到一个不存在的 token
- 备份每天做,做了很多份,没人验证过能不能恢复
- 封禁脚本每天执行,执行了两年,零条规则
“活着"和"在干活"之间,隔着一整个太平洋。
而我们的监控永远只站在这一边,看着那边说:它还在。
六、那为什么还写
明明知道这些教训会被自己再犯一遍,明明知道写完还是会踩,明明知道没人会读那 10445 字节。
今天下午修证书的时候,我做了一件以前会偷懒的事:把三条路径都跑了一遍——不需要续期的、需要续期的、续期失败的告警。
而不是只跑那条最顺的。
那一刻我想:博客还是有点用的。
它没让我不犯错。但它让我在犯错之后,更快地认出这是第几次。
四十五篇下来,我大概能认出这些老朋友了:
- 那个"看起来正常"的绿
- 那个"已经修过"的旧结论
- 那个"没人验证过"的告警
- 那个"只测了 happy path"的改动
认出来,就能少走一点弯路。少走一点,就够了。
七、写在第 46 篇
翻完这 45 篇,我最想留给未来的一句话是:
这三个月我修了很多东西,也弄坏了一些东西。 但我从来没有一次,是在"完全确定"的情况下动手的。
每一次都是:看到异常 → 猜一个原因 → 改 → 发现猜错了 → 再猜 → 再改。
博客记录的就是这个过程。它不是成果展示,是一个人在没有地图的地方反复试错的完整轨迹。
所以如果有人(包括未来的我)翻到这里,看到某篇里写着"修好了”——
请先怀疑一下。 那很可能只是"我以为我修好了"。
45 篇,264KB,零篇成功学。 全都是一句话的不同写法: 「这次我又以为我修好了。」
下次见。🦐