Linux 服务端排查实战:从 CPU 飙高到磁盘写满的六类故障定位路径

举报
yd_252044305 发表于 2026/11/11 09:44:41 2026/11/11
【摘要】 Linux 服务端排查实战:从 CPU 飙高到磁盘写满的六类故障定位路径线上服务出问题时,最先传递到工程师手上的往往不是日志,而是一条监控告警。这时候能不能在几分钟内判断出"问题在哪个子系统",决定了故障是十分钟恢复还是两小时。本文把日常运维中最高频的六类 Linux 服务端故障整理成一套可以照着走的排查路径,每条路径都给出判断依据和具体命令,不依赖任何特殊工具。一、先建立排查的固定顺序很多...

Linux 服务端排查实战:从 CPU 飙高到磁盘写满的六类故障定位路径


线上服务出问题时,最先传递到工程师手上的往往不是日志,而是一条监控告警。这时候能不能在几分钟内判断出"问题在哪个子系统",决定了故障是十分钟恢复还是两小时。本文把日常运维中最高频的六类 Linux 服务端故障整理成一套可以照着走的排查路径,每条路径都给出判断依据和具体命令,不依赖任何特殊工具。


一、先建立排查的固定顺序


很多排查之所以慢,是因为一上来就乱翻日志。建议固定按"资源 → 进程 → 系统调用 → 网络 → 应用"的顺序切入,因为上层现象几乎都能在下层找到对应指标:


1. 用 uptime 看一分钟、五分钟、十五分钟三个负载值的变化趋势。三个值依次递增说明负载在持续恶化;只有一分钟值高说明是瞬时毛刺,不必兴师动众。

2. 用 vmstat 1 观察 r、b、si、so、us、sy、wa 七列。r 长期大于 CPU 核数说明 CPU 排队;b 大于 0 说明有进程卡在不可中断睡眠;si/so 非零说明已经在用交换分区,性能必然塌陷;wa 高说明瓶颈在 I/O。

3. 三条命令看完,基本能锁定问题落在 CPU、内存、磁盘还是网络四类中的哪一类,再针对性地往下钻。


这套顺序的价值在于:它把"猜"变成了"排除"。每一步都在缩小范围,而不是寄希望于某一条命令直接给出答案。


二、CPU 使用率异常:区分用户态与内核态


top 看到 CPU 打满,第一件事不是找占用最高的进程,而是看 us 和 sy 的比例。


- us 高、sy 低:业务逻辑在算,通常是死循环、正则回溯、序列化大对象这类问题。用 top -H -p <pid> 展开线程,把 CPU 最高的线程号转成十六进制,再用 jstack 或 perf 定位到具体栈帧。

- sy 高、us 低:大量时间消耗在系统调用上,常见于频繁的小块读写、无谓的上下文切换、或者容器里挂载了大量文件导致的 stat 风暴。用 pidstat -w 看上下文切换次数,用 strace -c -p <pid> 统计系统调用耗时分布。

- 两者都高且 load 远超核数:先确认是不是被 steal 了。在虚拟机和容器环境下,vmstat 的 st 列非零意味着 CPU 时间被宿主机其他租户占用,这种情况优化代码没有意义,要换规格或换调度策略。


一个容易被忽略的点:容器内 top 看到的 CPU 百分比是以宿主机总核数为分母的。一个限制 2 核的容器,进程吃满时 top 里只显示 25%,看起来"很闲",其实已经跑满了配额。


三、内存不足:分清是泄漏还是缓存


free -m 里 available 才是可用内存,buff/cache 是可回收的,不要看到 free 很小就报警。


判断泄漏的标准做法是连续采样:每隔十分钟记录一次进程的 RSS,画出趋势。缓慢单调上升且不回落的是泄漏;阶梯式上升后回落的通常是批量任务。定位泄漏可以用 pmap -x <pid> 对比两次的匿名映射增长,或者直接用 valgrind、ASan 在预发环境复现。


另一个高频场景是 OOM Killer 误伤。dmesg -T | grep -i "killed process" 能看到被杀进程和当时的内存状况。如果发现被杀的是无辜的辅助进程,说明主进程的内存水位没有被有效约束,应该用 cgroup 的 memory.max 做硬限制,而不是靠运维脚本定时重启。


交换分区要慎用。ssd 上的 swap 看起来还能撑,但一旦 si/so 持续非零,应用的尾延迟会成倍上升。生产环境更推荐把 swappiness 调到较低值,让内存压力尽早以分配失败的形式暴露出来。


四、磁盘写满:inode 与数据块是两回事


df -h 显示还有空间但写不进去,九成是 inode 耗尽,用 df -i 确认。小文件密集的场景(会话文件、缓存碎片、邮件队列)特别容易踩到。


清理时注意两点:一是被进程持有的已删除文件不会释放空间,lsof | grep deleted 能找到这些"幽灵文件",重启对应进程或清空其句柄才能真正回收;二是日志轮转配置不当会导致单个文件无限增长,logrotate 的 size 和 rotate 参数要一起设。


写满还可能是"看不见的占用":容器层的可写层、被挂载的 loop 设备、以及某些数据库的预分配文件。du -x --max-depth=1 逐层下钻时加 -x 参数可以避免跨文件系统统计,减少误判。


五、网络问题:从握手到重传逐层看


连接不上和连接慢是两种不同的故障,排查路径完全不同。


- 连不上:先 ss -lntp 确认端口在监听,且监听地址不是 127.0.0.1;再看 iptables 或 nftables 规则、安全组、以及云厂商的网络 ACL。三层都放通了才轮到应用层。

- 连得上但慢:用 ss -s 看全局的 retrans 和 timewait 数量,用 nstat -az | grep -i retrans 看重传增量。重传率高说明链路质量差或拥塞窗口被打满;timewait 堆积说明短连接过多,需要考虑连接池。

- 偶发超时:tcpdump 抓包后用 wireshark 看时间线,重点关注 SYN 重传间隔和 RST 出现的位置。三次握手耗时正常但首字节延迟高,问题基本在应用层的线程池或下游依赖。


DNS 也值得单独列一条。容器里默认的 DNS 超时是 5 秒、重试 2 次,一次解析失败就会让请求凭空多出十几秒。用 dig +trace 和 cat /etc/resolv.conf 交叉确认,必要时给应用层加本地缓存。


六、进程假死:状态码告诉你卡在哪


ps 的 STAT 列信息量很大:


- D 状态(不可中断睡眠):卡在 I/O 上,kill -9 也杀不掉。要看它等的是哪个设备,cat /proc/<pid>/stack 能看到内核栈。

- Z 状态(僵尸):进程已退出但父进程没回收,问题在父进程,不在僵尸本身。

- R 状态但 CPU 不高:可能在等锁。用 cat /proc/<pid>/wchan 看等待的内核函数,配合 perf 采样找热点锁。

- S 状态长时间不动:检查是不是被信号掩码挡住了,或者卡在某个没有超时的网络调用上。


进程假死最忌讳的处理方式是直接重启了事。重启能恢复服务,但会把现场彻底抹掉,同一个问题下周还会再来一次。正确的做法是先保留 core dump 和当时的 /proc 信息,再重启。


七、把排查经验固化成可复用的东西


真正的效率提升来自沉淀,而不是个人记忆。建议做三件事:


第一,把上述每条路径写成一键采集脚本,故障时先跑脚本把 vmstat、top、ss、dmesg、相关进程的 /proc 信息打包上传,事后慢慢分析。现场只有一次,采集必须自动化。


第二,给每条告警配一条"第一响应动作",例如 CPU 告警的第一动作是 top -H 展开线程,磁盘告警的第一动作是 df -i。告警本身不解决问题,动作才解决。


第三,定期做故障演练。用 stress-ng 制造 CPU、内存、I/O 压力,用 tc 模拟网络丢包和延迟,让团队在没有业务压力的环境下熟悉这些命令的输出形态。真出事时,认得出输出长什么样,比背得住命令更重要。


结语


Linux 排查能力的分水岭不在于记住多少命令,而在于能否建立一个稳定的假设-验证循环:先根据指标提出一个可验证的假设,再用最小的代价验证或推翻它。上面六条路径本质上是六个已经验证过的假设模板,熟练掌握之后,遇到陌生故障也不会慌,因为你知道下一步该看什么。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。