引言
线上故障发生时,时间就是金钱,心态就是产能。运维工程师最常遇到的三类故障并非软件 Bug,而是”系统起不来””机器跑不动””网络连不上”——这三类故障占生产事故的比例通常超过 70%。它们往往没有显式的错误日志,没有明确的告警阈值,靠的是一套可复用的 排查方法论 与 诊断命令组合拳,而不是临时抱佛脚。
本文将以 Ubuntu 22.04 / 24.04 LTS 为底座,系统讲解这三类高频故障的定位流程:从启动链路的 initrd 到 GRUB、从 CPU/内存/IO 三维负载模型到进程归因、从 Netplan 到路由表、从 ARP 到 DNS 的逐层下钻,并给出可直接套用的命令清单与应急脚本。读完本篇,你将拥有面对大多数 P1 故障时的”先做什么、再看什么、最后处理什么”的肌肉记忆。

一、故障排查的通用方法论:分治与分层
1.1 五步定位法
无论故障表象如何,都建议遵循一条固定路径:
- 复现与止损:先止血(重启、摘流量、降级),保留现场(截图、日志、core dump)。
- 缩小范围:分层确认——硬件层 / 内核层 / 系统层 / 应用层。
- 采集证据:使用系统内置工具采集指标,避免”凭感觉”。
- 定位根因:把异常指标对应到具体进程、服务、配置或硬件。
- 修复与回归:修复 → 灰度 → 全量,补充监控与告警,更新 Runbook。
1.2 三类故障的边界
| 类型 | 典型表象 | 优先级工具 |
|---|---|---|
| 启动失败 | 蓝屏、GRUB 报错、卡在 initramfs |
dmesg, journalctl -b -1, grub-mkconfig |
| 高负载 | CPU 打满、load average 飙升、磁盘 iowait 高 |
top, vmstat, iostat, pidstat |
| 网络异常 | 丢包、延迟高、Connection refused |
ss, tcpdump, mtr, iptables -L |
二、启动失败排查实战
2.1 启动链路回顾
Ubuntu 的启动链路为:固件(UEFI/BIOS) -> GRUB -> Linux Kernel -> initramfs -> systemd(PID 1) -> 服务单元。任一环节异常都可能表现为”系统起不来”。
# 通过 GRUB 菜单进入 Advanced options,选择带 (recovery mode) 的内核
# 启动后按 Esc 中断,进入 GRUB 编辑界面,修改 root= 或 initrd= 参数
2.2 场景 A:卡在 “Loading initial ramdisk” 或 initramfs 提示符
这通常意味着 initrd.img 损坏或 root 分区找不到。处理步骤:
# 从 Live USB 启动,挂载根分区
sudo fdisk -l
sudo mount /dev/sda2 /mnt
sudo mount /dev/sda1 /mnt/boot # 若 /boot 独立分区
sudo chroot /mnt
# 重新生成 initramfs
update-initramfs -u -k all
grub-mkconfig -o /boot/grub/grub.cfg
exit
sudo reboot
2.3 场景 B:进入 GRUB 后无法启动(Kernel panic)
最常见的根因是内核参数错误或磁盘设备名变更(如 /dev/sda -> /dev/nvme0n1)。
# 使用 systemd-analyze 检查上次启动的失败原因
journalctl -b -1 -p err --no-pager | tail -50
systemd-analyze blame | head -20
# 若 boot 分区是 ext4,先检查文件系统一致性
sudo fsck -y /dev/sda1
2.4 场景 C:systemd 起不来(一直停在 “Starting…”)
systemctl list-jobs 和 systemd-analyze critical-chain 能快速找出阻塞的 Unit:
systemctl list-jobs
systemd-analyze critical-chain
journalctl -u NetworkManager -b --no-pager
三、高负载排查实战
3.1 读懂 load average
uptime 输出的 1.00, 0.85, 0.72 分别是 1/5/15 分钟的平均负载。Linux 内核中,”处于运行队列或 D 状态(不可中断睡眠)的任务数”会被计入,因此 load > CPU 核数 不一定意味着 CPU 满,但 load 远高于核数 + iowait 高 则一定是 IO 瓶颈。
# 实时查看 CPU 核数与负载
nproc
uptime
cat /proc/loadavg
3.2 CPU 高负载定位
top 是最快的入口,使用 P 按键按 CPU 排序,再用 Shift+P 锁定排序:
top -o %CPU -b -n 1 | head -20
# 或 pidstat 查看单进程 CPU 耗时
pidstat -u -p <PID> 1 5
如果是”系统态(sy)”占比高(如 sy 80%),常见根因是内核中断风暴或大量 syscall,可用 perf top 定位:
perf top -g
perf stat -p <PID> -- sleep 5
3.3 内存与交换异常
# vmstat 查看上下文切换、swpd 使用情况
vmstat 1 5
# free -h 看缓存回收情况
free -h
# 查看进程内存占用
ps aux --sort=-%mem | head -10
# 若出现 OOM Killer
journalctl -k -b --no-pager | grep -i oom
dmesg -T | grep -i -E "out of memory|oom"
3.4 IO 瓶颈定位
# iostat -x 2 查看每块盘 await / %util
iostat -x 2
# pidstat -d 1 找出哪个进程写入/读取最多
pidstat -d 1
# lsof 看哪个进程持有了大量打开文件
lsof +L1 # 查找已删除但仍被占用的文件
3.5 高负载应急脚本
下面是一个 5 秒快照脚本,适合在事故现场一键采集:
#!/bin/bash
OUT="/tmp/hotspot-$(date +%Y%m%d-%H%M%S).log"
{
echo "===== $(date) uptime ====="; uptime; nproc
echo "===== vmstat ====="; vmstat 1 3
echo "===== free ====="; free -h
echo "===== top CPU ====="; ps -eo pid,ppid,cmd,%cpu,%mem --sort=-%cpu | head -15
echo "===== iostat ====="; iostat -x 1 3
echo "===== df ====="; df -hT
echo "===== dmesg last 30 ====="; dmesg -T | tail -30
} > "$OUT" 2>&1
echo "Snapshot: $OUT"
四、网络异常排查实战
4.1 排查顺序:本地 -> 链路 -> 路由 -> 名字解析
# 1) 网卡是否 up、是否有 IP
ip addr show
ip -s link
# 2) 本机监听端口与连接状态
ss -tulpn
ss -s
# 3) 路由表与策略路由
ip route show
ip rule show
# 4) ARP 与邻居
ip neigh show
4.2 DNS 异常定位
# 查看 resolv.conf 是否被覆盖
cat /etc/resolv.conf
# systemd-resolved 场景
resolvectl query example.com
resolvectl status
# 使用指定 DNS 测试
dig @8.8.8.8 example.com +short
dig example.com +trace
4.3 抓包定位连接异常
# 抓目标 IP 的所有 TCP 流量,前 100 包
sudo tcpdump -i any -nn host 10.0.0.5 and tcp -c 100 -w /tmp/cap.pcap
# 快速看包统计
tcpdump -r /tmp/cap.pcap -nn
4.4 防火墙与 iptables 排查
# 查看 UFW 状态与规则
sudo ufw status verbose
sudo iptables -L -v -n --line-numbers
# 临时放行某端口
sudo iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
4.5 网络性能排查
# mtr 替代 ping+tracert
mtr -rwzbc 100 8.8.8.8
# iperf3 测带宽(服务端)
sudo apt install -y iperf3
iperf3 -s
# 客户端测试上行/下行
iperf3 -c 10.0.0.100 -t 30 -P 4
五、常见问题与应急处理速查
Q1:systemctl 提示 “failed to get unit file state”
通常是 /etc/systemd/system/*.wants 目录里有损坏的符号链接。用 systemd-analyze verify /etc/systemd/system/ 检查,删除无效链接即可。
Q2:journalctl 报 “No journal files were found”
可能是 /var/log/journal 权限错误或 Storage=volatile。检查 /etc/systemd/journald.conf,并执行 sudo systemctl restart systemd-journald。
Q3:tcpdump 抓到大量 RST
RST 通常由应用主动关闭或防火墙丢弃触发。先 ss -tan state established 看连接状态,再对照 iptables -L -v -n 的计数器,定位是哪条规则丢弃了包。
Q4:开机后某服务随机未启动
用 systemd-analyze blame 找最慢的 Unit,再查其 ExecStart 是否依赖尚未就绪的资源(如网络、磁盘挂载)。可改用 After=network-online.target 或 RequiresMountsFor=。
Q5:load 高但 CPU 空闲(iowait 高)
这是典型的 IO 瓶颈。用 iostat -x 1 看 %util 是否接近 100%,pidstat -d 找出写盘大户。若是日志写入,开启异步日志或调整 fsync 策略;若是数据库,考虑分离数据盘或升级为 NVMe。
六、总结
故障排查并非玄学,而是一套 可复用、可训练 的流程。掌握以下要点即可覆盖 80% 的 Ubuntu 生产故障:
- 分层定位:先硬件、再内核、再系统、最后应用,避免”一上来就看应用日志”。
- 证据先行:所有结论必须基于
top/vmstat/iostat/ss/tcpdump的输出,而不是猜测。 - 现场保留:使用
journalctl -b -1抓取上次启动日志,coredumpctl list保留崩溃现场。 - 快速止血:能重启先重启、能摘流量先摘、能降级先降级,事后再做根因分析。
- 沉淀 Runbook:每次 P1 故障都应产出一页可执行手册,下次 3 分钟解决。
把今天的五步法、命令清单与应急脚本整理成你团队的 Runbook,下一次故障来临时,你需要的只是一次复制粘贴。
下期预告
下一篇(第 29 天)我们将进入 云原生运维——公有云 Ubuntu 实例管理与弹性伸缩,涵盖 AWS/GCP/阿里云的 Ubuntu AMI/镜像管理、实例规格选型、Auto Scaling 策略、跨可用区容灾与成本优化,带你从”单机运维”平滑过渡到”弹性集群运维”。敬请期待。
















暂无评论内容