Linux服务器故障排查:从系统僵死到根因定位的实战路径
服务器故障排查是运维工程师的日常,但很多排查过程缺乏系统性,靠经验和运气碰答案。这篇文章把常见的Linux服务器故障场景拆解为可复用的诊断流程,涵盖系统僵死、CPU飙高、内存泄漏、磁盘IO瓶颈四大典型问题,每个场景给出具体的诊断命令和判断逻辑,目标是让排查从”凭感觉”变成”走流程”。
系统僵死:先判断是死锁还是资源耗尽
服务器无响应是最紧急的故障场景。接到告警后,第一件事不是重启,而是判断系统是否还活着:
# 检查内核是否响应(Magic SysRq)
echo t > /proc/sysrq-trigger
# 尝试非交互式登录
ssh -o ConnectTimeout=5 root@server "echo alive"
# 如果SSH不通,尝试串口控制台或IPMI
ipmitool -H 192.168.1.100 -U admin -P password sol activate
如果内核还能响应SysRq,说明是用户态问题(进程死锁或资源耗尽);如果连SysRq都无响应,大概率是内核panic或硬件故障,需要看IPMI的SEL日志。
用户态死锁的典型特征是多个进程都在D状态(uninterruptible sleep):
# 查看D状态进程
ps aux | awk '$8 ~ /D/ {print}'
# 查看进程等待的内核函数
cat /proc/<pid>/wchan
# 查看所有进程的堆栈
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
echo "=== PID $pid ==="
cat /proc/$pid/stack 2>/dev/null
done | head -200
D状态进程大量堆积,通常指向IO问题——存储设备响应慢或NFS挂载点卡死。如果是NFS导致的,立即强制卸载:
# 强制卸载卡死的NFS
umount -f /mnt/nfs_share
# 如果umount也卡住
umount -l /mnt/nfs_share # lazy unmount
CPU飙高:定位到具体函数的排查流程
CPU使用率告警是最常见的告警类型,但”CPU高”本身不是根因,需要定位到具体是什么代码在消耗算力。
# 第一步:确认是用户态还是内核态
vmstat 1 5
# us列高 = 用户态(应用代码问题)
# sy列高 = 内核态(系统调用或锁竞争)
# 第二步:找到吃CPU的进程
top -H -b -n1 | head -20 # -H显示线程级别
# 第三步:对目标进程做火焰图
perf record -g -p <pid> -- sleep 30
perf script | stackcollapse-perf.pl | flamegraph.pl > cpu.svg
# 或用更轻量的bpftrace
bpftrace -e 'profile:hz:99 /pid == <pid>/ { @stack[kstack] = count(); }'
如果内核态CPU高,常见原因:
- 大量短连接导致TIME_WAIT堆积 → 内核协议栈开销大
- 频繁的epoll_ctl调用 → 连接管理效率低
- spinlock竞争严重 → 多线程架构问题
处理短连接堆积:
# 查看TIME_WAIT数量
ss -ant state time-wait | wc -l
# 内核参数调优
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_max_tw_buckets=65535
内存泄漏:从现象到代码行的精准定位
内存持续增长但不释放,是服务器安全加固之外同样棘手的问题。排查步骤:
# 监控进程内存变化
while true; do
echo "$(date +%H:%M:%S) RSS=$(ps -o rss= -p <pid>) kB"
sleep 60
done
# 用smem看实际物理内存占用(含共享库分摊)
smem -p | grep <process_name>
# 用pmap看内存映射分布
pmap -x <pid> | tail -5
确认是泄漏而非正常缓存后,需要定位泄漏点。Java应用用jmap+MAT分析堆转储,Go应用用pprof,C/C++用Valgrind或AddressSanitizer:
# Java堆转储
jmap -dump:live,format=b,file=heap.hprof <pid>
# Go pprof
curl http://localhost:6060/debug/pprof/heap > heap.pprof
go tool pprof -http=:8080 heap.pprof
# C/C++ Valgrind(测试环境)
valgrind --leak-check=full --show-leak-kinds=all ./your_program
内存泄漏的临时缓解措施是设置进程内存上限并配置自动重启:
# systemd服务限制内存
[Service]
MemoryMax=4G
MemoryHigh=3.5G
磁盘IO瓶颈:如何区分是慢盘还是业务过载
IO等待高时,需要区分是存储设备本身变慢,还是业务IO量过大导致排队:
# 看IO等待和队列深度
iostat -x 1 10
# 关键指标:
# %util > 95% → 设备饱和
# await > 20ms → 响应慢(SSD正常值<2ms)
# svctm > 10ms → 设备本身慢
# avgqu-sz > 2 → 队列积压
如果svctm高而队列短,说明是设备本身变慢——可能是SSD寿命到了或HDD有坏道。用smartctl检查:
smartctl -a /dev/sda | grep -E "Reallocated|Current_Pending|Offline_Uncorrectable"
如果svctm正常但队列深,说明是业务IO量太大。优化方向:
# 1. 减少随机IO——检查是否有大量小文件读写
strace -e trace=read,write -p <pid> -c
# 2. 调整IO调度器(机械硬盘用deadline,SSD用noop/mq-deadline)
cat /sys/block/sda/queue/scheduler
echo "mq-deadline" > /sys/block/sda/queue/scheduler
# 3. 增加预读缓存
blockdev --setra 4096 /dev/sda
服务器故障排查的标准化清单
把这些诊断流程沉淀为标准化的检查清单,每次故障时按顺序执行,能显著减少MTTR(平均恢复时间):
- 确认连通性(SSH、IPMI、串口)
- 检查系统负载分类(CPU用户态/内核态、内存使用、IO等待)
- 查看内核日志(dmesg -T | tail -50)
- 查看关键服务状态(systemctl status)
- 查看磁盘和文件系统状态(df -h, smartctl)
- 查看网络状态(ss -s, conntrack数量)
每个步骤的超时时间不要超过2分钟,2分钟内无法定位就升级处理。高可用集群环境下,优先切换流量到健康节点,再对故障节点做离线分析。算力资源规划中预留的冗余容量,就是给这种故障窗口用的。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-fu-wu-qi-gu-zhang-pai-cha-shi-zhan-cong-xi-tong-jiang/