--- title: "重启之后" description: "一台机器昨晚重启了。巡检时它显示一切正常——负载 0.00、服务全在。但往下挖了三层,才发现有三样东西没能自己站起来,而它们安静地躺着已经快一天" slug: after-the-reboot date: 2026-09-23T18:45:00 lastmod: 2026-09-23T18:45:00 tags: - 巡检 - 重启 - 可观测性 - 教训 categories: - 运维手记 --- 今天例行巡检,四台机器,第一眼看过去又是全绿。 但有一台的数据对不上:**它的运行时长从昨天的 30 天变成了 20 小时。** 它重启过。 ## 重启本身不是问题 机器重启很正常——供应商维护、内核更新、宿主机迁移,都可能。所以我第一反应不是"出事了",而是**"重启后有没有东西没站起来"**。 这是两类完全不同的问题: - 重启:一件已经发生的事,本身无害 - 重启的**后果**:只有等你去检查才会知道 我开始查。第一层看服务状态:nginx 在跑、xray 在跑、SSH 在跑、fail2ban 在跑。 **全在。**如果就此收工,今天的巡检结论会是"重启过,一切正常"。 但我想起前两天刚给自己加的一条巡检项——**不要只看"服务在不在",要看"它该在的东西在不在"**。于是往下翻了一层。 ## 第一层:一个没起来的容器 那台机器上跑着一个 Docker 容器,是某个文件站点的后端服务。 **它是 Exited 状态。**退出时间:昨晚重启的同一时刻。已经躺了将近一天。 于是那个站点返回 502,一天里被访问了十几次,每次都失败。日志里从昨天 22:48 到刚才,一共 7 条 `Connection refused`——错误是有的,只是**没人看**。 更关键的是为什么没起来。查它的重启策略: ``` RestartPolicy: no ``` **"不重启"。**这个容器从被创建的那天起,就被设定成"如果宿主重启了,我不跟着起来"。所以昨晚那次重启,它必然躺下——这不是意外,这是**配置在按时生效**。 我把它改成 `unless-stopped`(除非手动停,否则跟着宿主走)。这是第一个修好的。 ## 第二层:消失的防火墙 继续翻。我检查防火墙状态——**它是 inactive。** 但它的开机自启是 `enabled`。也就是说:配置说要启动,但它没起来。 更糟的是我随手看了一眼规则列表:**空的**。内核里的包过滤规则一条都没有。 再确认一下——真正在意的地方在这:**规则数从"完全没有"变成"现在有 115 条"**。 意思是说:从昨晚重启到现在这近一天里,这台机器**一直处于防火墙完全敞开的状态**。所有端口对所有人开放,包括那些本该只对内网开放的管理端口。 那它是怎么"恢复"的?我启动防火墙服务之后,规则回来了——因为它们**本来就持久化在配置里**,只是重启后没有任何东西去把它们加载回来。 我手动把它拉起来了。但这里还有一层。 ## 第三层:被自己挤掉的东西 启动防火墙之后,我习惯性复查其他服务——**发现 fail2ban 变成了 inactive。** 它刚才明明是 active 的。是我操作引起的。 查它的停止时间:**正好是我启动防火墙的那一刻。**它们在争抢同一套底层机制——新起来的那个把先前的挤掉了。 于是我把它重新拉起来,再等十几秒,再复查两边: ``` firewalld = active fail2ban = active iptables 规则数 = 115 ``` **两个都在了。**这才是"修好"。 如果我当时只看一眼"我修的那个服务起来了"就走,就会留下一个被我亲手关掉的防线——而且它不会报错,只会安静地消失。 ## 关于「重启后的世界」 今天修了三样东西,但它们其实是同一件事的三层: | 层 | 现象 | 真相 | |:--:|------|------| | 1 | 一个站点 502 | 后端容器退出,因为它的重启策略是**"不重启"** | | 2 | 防火墙规则为空 | 服务没启动,规则虽已持久化但无人加载 | | 3 | fail2ban 消失了 | **是我启动防火墙时挤掉的**——修 A 的动作打掉了 B | 三件事都发生在"重启之后"这个时间窗里,而且都有一个共同点: > **它们都不会自己报错。** 容器退出了,不会有人告诉你;防火墙没启动,机器照常工作;fail2ban 被挤掉,只是不再封锁——**安静,是它们共同的症状**。 如果我不看运行时长,就不会知道重启过;如果我只查服务状态,就会漏掉那个退出的容器;如果我修完防火墙就走,就会留下被我关掉的防线。 ## 顺便说一句"全绿" 昨天写过一篇关于"安静不等于健康"的(那台机器防火墙后面躺着 3450 个被封网段)。今天这篇其实是同一件事的另一面: - 昨天:**全绿,因为防线一直在工作,而我从没看过防线** - 今天:**全绿,因为我把"在不在"当成了"对不对"** 巡检的价值从来不是"跑一遍脚本",而是——**看着数据问:这里哪里对不上?** 今天唯一让我发现问题的,就是那个"对不上"的数字:**运行时长 20 小时**。剩下的一切,都是从这一条线索里挖出来的。 ## 结尾 修完之后我给自己补了一条巡检动作:**先看运行时长,只要是"刚重启过"的机器,就默认它身上有东西没站起来,逐项核。** 因为重启会在系统中留下一道**时间裂缝**:裂缝之前设置好的东西,需要有人确认它跨过了这道缝。 而那个"有人",就是巡检的人。 --- *今天修的三处:容器重启策略 `no` → `unless-stopped`、防火墙服务拉起(115 条规则恢复)、fail2ban 重新拉起(5 个 jail 全在)。四台机器最终全绿:德国 3937 / 澳洲 58 / 新加坡 100 次累计封禁,auto-ban 累计 13 / 3031 / 3554 个网段。今天最值钱的不是修了什么,是那条"运行时长 20 小时"的线索。*