作为在Linux运维一线摸爬滚打多年的老鸟,我见过太多新手面对系统故障时的手足无措。服务器突然卡死、应用莫名崩溃、网络时断时续——这些问题往往就出在CPU、内存、硬盘和网络这四大核心组件上。今天我就用实战中积累的"望闻问切"手法,带大家建立系统化的排查思维。
不同于教科书式的理论讲解,我们直接从生产环境中最常见的异常现象切入。当监控系统发出警报时,有经验的工程师会像老中医把脉一样,通过几个关键指标快速定位问题根源。比如CPU负载飙升可能由死循环线程引起,内存泄漏往往伴随cache持续增长,硬盘IO瓶颈会导致进程D状态堆积,而网络丢包则可能引发TCP重传风暴。
当top命令显示load average超过CPU核数2倍时,就需要立即介入排查。我常用的诊断组合拳是:
bash复制top -H -p $(pgrep -d, 进程名) # 查看具体线程CPU占用
perf top -g -p 进程PID # 性能热点分析
strace -ff -T -p 进程PID # 系统调用追踪
去年我们有个Java应用CPU持续100%,通过perf发现是正则表达式回溯导致的。这时jstack输出的线程堆栈显示多个线程卡在java.util.regex.Pattern的匹配操作上,最终通过优化正则表达式解决。
某次线上ksoftirqd进程占用30%CPU的案例让我记忆犹新。通过监控发现每秒网络中断次数突破5万次:
bash复制watch -n 1 'cat /proc/interrupts | grep eth0'
最终确认是网卡驱动bug导致的中断风暴,临时方案是通过ethtool -C eth0 rx-usecs 100调整中断合并阈值,根本解决则需要升级驱动版本。
重要提示:CPU软中断过高时,务必检查
/proc/softirqs中各类型中断的分布情况,网络收包通常体现在NET_RX项
当free -h显示available内存不足时,内核的OOM Killer可能随时触发。我们需要提前预防:
bash复制dmesg -T | grep -i oom # 查看历史OOM记录
cat /proc/meminfo | grep -E 'MemAvailable|SwapCached'
通过pmap -x 进程PID可以分析具体进程的内存分布,我曾用这个方法发现一个PHP进程竟然映射了2GB的共享内存。
对于疑似内存泄漏的应用,我的排查三板斧:
valgrind --leak-check=full 可执行文件gdb -p 进程PID后执行malloc_info 0 /tmp/mem.xml/proc/[pid]/smaps中私有脏页的变化去年一个C++服务每周泄漏800MB内存,最终通过mtrace工具定位到是未释放的第三方库分配的内存。
当应用响应变慢时,先用iostat -x 1查看关键指标:
某次MySQL查询变慢案例中,发现avgqu-sz持续大于32,说明IO队列堆积,最终通过增加SSD解决。
lsof -p 进程PID | wc -l可以统计进程打开的文件数。如果持续增长,需要检查:
bash复制ls -l /proc/[pid]/fd | grep deleted # 查找未关闭的文件
strace -e trace=open,close -p 进程PID
曾遇到一个Tomcat应用fd突破1万上限,原来是开发人员忘记关闭XML解析器的InputStream。
当conntrack -L执行卡顿时,可能是连接跟踪表满了:
bash复制dmesg | grep nf_conntrack
sysctl net.netfilter.nf_conntrack_max # 建议调整为655350
某次视频直播服务卡顿,就是因为默认的nf_conntrack_max=65536不够用,调整后立即恢复。
通过ss -itp查看各连接的retrans信息。对于频繁重传的情况:
bash复制ethtool -K eth0 tso off gso off # 关闭分段卸载
sysctl -w net.ipv4.tcp_sack=0 # 关闭SACK选项
实际案例显示,某些老款网卡驱动开启TSO会导致TCP校验和错误,进而引发重传风暴。
我常用的快速检查脚本:
bash复制#!/bin/bash
echo "----CPU----"
uptime; mpstat -P ALL 1 3
echo "----Memory----"
free -h; vmstat 1 5
echo "----Disk----"
iostat -x 1 3; df -h
echo "----Network----"
sar -n DEV 1 3; netstat -s
bpftrace:动态内核追踪systemtap:深度性能分析ebpf:新一代观测工具最近用bpftrace定位过一个分布式锁竞争问题,脚本如下:
bash复制bpftrace -e 'kprobe:mutex_lock { @[comm] = count(); }'
不要盲目重启:曾经有次直接重启导致OOM现场丢失,后来养成了先vmcore-dmesg /proc/vmcore保存内核日志的习惯
监控基线很重要:所有关键指标都要建立正常基线,比如MySQL服务器的%sys通常<5%,超过15%就异常
时间戳是生命线:所有诊断命令都要带时间戳,建议alias常用命令:
bash复制alias now='date "+%Y-%m-%d %H:%M:%S"'
alias mytop='top -b -n 1 | sed "s/^/$(now) /" >> /var/log/top.log'
markdown复制## 2023-08-15 Kafka消费延迟
现象:consumer_lag突增
关键指标:
- 网络:sar -n DEV 1 显示rxdrop增加
- 磁盘:iostat显示%util 95%
解决方案:调整网卡ring buffer + 增加磁盘
这些年在故障排查中最大的体会是:所有异常都有迹可循。关键是要建立系统化的排查思路,像侦探破案一样层层抽丝剥茧。每次解决一个疑难杂症,都是对技术理解的又一次升华。