从什么都不知道开始
一句话总结
面对陌生系统时,最初 30 分钟要做的不是修复问题,而是确定哪些内容不必再看。
为什么需要了解这一点
如果是自己团队的服务,收到故障报告时往往会立刻动手。因为 dashboard 在哪里、日志积累在哪个目录、昨天谁部署了什么,这三件事早已在脑中。到了客户现场,这些信息全都没有。你不知道监控是什么,不知道日志位置,也不知道昨天发生了什么变化,身旁还有人在追问什么时候能修好。
在这种条件下,区分经验丰富者和经验不足者的,不是知识量,而是顺序。没有顺序,就会先打开显眼的日志;陌生环境中的日志如同大海,两小时后依然停在原地。
所以第一步永远是侦察。不是寻找要修的东西,而是绘制地形。
工作原理
侦察时需要确认四件事。
第一,访问方式与权限。 本能会让人先打开日志,但如果诊断途中才发现没有权限,那么申请和审批所需的时间都会白白浪费。更糟的是超越权限范围的行为。在客户生产环境中,一条越权命令造成的信任损失可能比故障更大。开始前,要在 ticket 顶部写明当前拥有的是读权限还是写权限,以及环境是 production 还是 staging。
第二,系统建立在什么之上。 发行版、内核、运行中的进程、开放的端口。仅 /etc/os-release 这一行,就会决定后续所有命令的语法。就连默认日志路径也不同:RHEL 系列是 /var/log/messages,Debian 系列是 /var/log/syslog。直接照搬别人的文档时,这里最容易出错。
第三,数据在哪里、有多少。 哪个文件最大、日志有多少行、采用什么格式。如果不知道大小,就无法预测一条 grep 要在几秒还是几分钟内结束;对于已经承受负载的系统,诊断命令本身还可能加剧故障。
第四,资源余量。 这里必须查看两次。用 df -h 查看容量,再用 df -i 单独查看 inode,因为容量与 inode 是完全不同的资源。
实际工作中的表现
先介绍一个最常见的陷阱。应用程序因“No space left on device”而终止,但 df -h 显示仍有 30% 空间。此时原因有三种可能:inode 已耗尽;文件虽已删除但仍保持打开,占用着 block;或者该路径实际上属于另一个 filesystem。
在 Linux 中,文件名不是实体本身,只是指向实体的一个引用。因此,即使删除名称,只要仍有进程打开该文件,block 就不会释放。所以日志轮转后,如果进程没有重新打开文件,被删除的日志仍会继续占用磁盘。当 df 与 du 的值差异很大时,几乎总是这个原因。
仅仅知道这一点,在处理“磁盘已满”的报告时就能比别人节省 20 分钟。而这 20 分钟,正是 FDE 所出售的价值。
侦察要留下什么
侦察的产物不应只留在脑中,而必须成为文档。理由有两个。第一,下次查看同一个系统时(或换成其他人查看时),不必重新花费 30 分钟。第二,向客户展示“我们已经掌握了什么”本身就能建立信任。即使第一天什么都没修好,只要产出一张地图,那段时间就不算浪费。
环境地图应包含的内容大致固定。
- 访问路径与权限——使用什么账户进入哪里、拥有读权限还是写权限,以及该服务器是否为生产环境。
- 正在运行什么——进程、开放端口,以及它们如何彼此调用。仅靠端口列表就能看出一半依赖关系。
- 数据在哪里——日志、数据目录、配置文件,以及各自的大小与格式。
- 资源余量——同时记录容量和 inode。
- 未知事项——这一项最重要。必须如实记下未能确认的内容,才不会在之后忘记自己曾在该处作出假设。
这份文档唯一的规则是:不要把猜测与已经确认的事实混在一起记录。“前端大概是 nginx”和“nginx 正在监听 80 端口”是两种不同的陈述,几天后却会变得无法区分。为确认过的事项一并记录验证命令,之后就能用同一命令重新检查状态是否变化。
最后,要为侦察设置时间上限。无论 30 分钟还是一小时,先确定期限;期限内没能画完,就保持未完成状态进入下一阶段。为了绘制完美地图而没能查看真正的问题,是仅次于不画地图直接冲进去的常见失败。
下个练习将做什么
进入假设为客户服务器的 Pod,确认发行版,创建数据 inventory,同时记录容量和 inode,留下一张环境地图。不会修复任何内容,只负责绘制。