摘要:服务器出问题时,快速定位根因是运维和后端开发的核心能力。本文总结CPU、内存、磁盘、网络四大类常见故障的排查套路,每个场景都有完整的命令链和分析思路。
排障总原则
遇到问题先别慌,按这个顺序来:
bash
# 第一步:看整体概况(5秒了解全局)
top -bn1 | head -20
free -h
df -h
场景1:CPU飙到100%
排查流程
bash
# 1. 找到占CPU最高的进程
top -c -o %CPU
# 2. 找到该进程中占CPU最高的线程
top -H -p <PID>
# 3. 如果是Java进程,导出线程栈
jstack <PID> > thread_dump.txt
# 把线程ID转16进制去栈里搜
printf '%x\n' <TID>
# 4. 如果是Python进程
py-spy top --pid <PID>
# 或者生成火焰图
py-spy record -o profile.svg --pid <PID>
常见原因
bash
# 死循环:strace看系统调用
strace -p <PID> -c -t
# 正则回溯:如果是Web服务,检查最近的请求日志
tail -f /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn
# 频繁GC(Java)
jstat -gcutil <PID> 1000
场景2:内存持续增长(疑似泄漏)
bash
# 1. 查看内存使用概况
free -h
cat /proc/meminfo
# 2. 按内存排序查看进程
ps aux --sort=-%mem | head -20
# 3. 查看某进程的内存映射
pmap -x <PID> | tail -5
# 4. 监控内存变化趋势
watch -n 5 'ps -o pid,rss,vsz,comm -p <PID>'
# 5. Python内存分析
pip install memory_profiler
python -m memory_profiler script.py
Python内存泄漏排查
python
# 方法1:tracemalloc(标准库)
import tracemalloc
tracemalloc.start()
# ... 运行一段时间 ...
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
print(stat)
# 方法2:objgraph(可视化对象引用)
import objgraph
objgraph.show_most_common_types(limit=20)
objgraph.show_growth(limit=10) # 两次调用之间增长最多的类型
场景3:磁盘空间满了
bash
# 1. 查看各分区使用率
df -h
# 2. 找到占空间最大的目录
du -sh /* 2>/dev/null | sort -rh | head -10
du -sh /var/* 2>/dev/null | sort -rh | head -10
# 3. 找大文件
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh | head -20
# 4. 已删除但未释放的文件(进程还在占用)
lsof +L1
# 5. 日志文件清理(不要直接rm正在写的日志!)
# ❌ rm /var/log/app.log # 空间不会释放
# ✅ 截断文件
> /var/log/app.log
# 或者
truncate -s 0 /var/log/app.log
自动清理脚本
bash
#!/bin/bash
# 清理30天前的日志
find /var/log -name "*.log" -mtime +30 -delete
find /tmp -type f -mtime +7 -delete
# 清理Docker
docker system prune -af --volumes
# 清理pip缓存
pip cache purge
# 清理apt缓存
apt-get clean
场景4:网络连接异常
bash
# 1. 查看网络连接状态统计
ss -s
# 2. 查看TIME_WAIT连接数
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
# 3. 查看某端口的连接
ss -tnp | grep :8080
# 4. 查看连接最多的IP
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
# 5. 抓包分析
tcpdump -i eth0 port 8080 -w capture.pcap -c 1000
# 6. DNS解析问题
dig example.com
nslookup example.com
time curl -o /dev/null -s -w '%{time_namelookup}\n' https://example.com
TIME_WAIT过多
bash
# 查看当前TIME_WAIT数量
ss -ant | grep TIME-WAIT | wc -l
# 临时优化(谨慎使用)
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=30
sysctl -w net.ipv4.tcp_max_tw_buckets=5000
场景5:进程僵死/无响应
bash
# 1. 查看进程状态
ps aux | grep <进程名>
# D状态 = 不可中断睡眠(通常是IO等待)
# Z状态 = 僵尸进程
# T状态 = 被暂停
# 2. 查看进程在做什么
strace -p <PID> -f -t
# 3. 查看进程打开的文件
lsof -p <PID>
# 4. 查看进程的网络连接
ss -tnp | grep <PID>
# 5. 如果是D状态(IO等待)
cat /proc/<PID>/stack
iostat -x 1 5 # 查看磁盘IO
场景6:系统负载高但CPU不高
bash
# load average高但CPU使用率不高,通常是IO等待
# 1. 确认IO等待
top # 看wa%(IO wait)
# 2. 找到IO最高的进程
iotop -o
# 3. 查看磁盘IO详情
iostat -xz 1 5
# 4. 查看哪个进程在读写什么文件
strace -p <PID> -e trace=read,write -c
实用排障工具箱
bash
# 安装常用工具
apt install -y sysstat htop iotop strace lsof net-tools dstat
# htop:增强版top
htop
# dstat:综合监控
dstat -cdnm 5 # CPU、磁盘、网络、内存,每5秒刷新
# sar:历史性能数据
sar -u 1 10 # CPU使用率
sar -r 1 10 # 内存使用率
sar -d 1 10 # 磁盘IO
sar -n DEV 1 10 # 网络流量
一键诊断脚本
bash
#!/bin/bash
echo "========== 系统概况 =========="
echo "主机名: $(hostname)"
echo "运行时间: $(uptime)"
echo "内核: $(uname -r)"
echo -e "\n========== CPU =========="
echo "核心数: $(nproc)"
echo "负载: $(cat /proc/loadavg)"
top -bn1 | head -5
echo -e "\n========== 内存 =========="
free -h
echo -e "\n========== 磁盘 =========="
df -h | grep -v tmpfs
echo -e "\n========== 网络连接 =========="
ss -s
echo -e "\n========== Top 10 CPU进程 =========="
ps aux --sort=-%cpu | head -11
echo -e "\n========== Top 10 内存进程 =========="
ps aux --sort=-%mem | head -11
echo -e "\n========== 最近错误日志 =========="
journalctl -p err --since "1 hour ago" --no-pager | tail -20
总结
排障的核心思路:
- 先看全局(top/free/df/ss),确定瓶颈在CPU/内存/磁盘/网络
- 定位到具体进程(ps/top排序)
- 深入分析(strace/lsof/pmap/tcpdump)
- 解决问题后做复盘,写入运维文档
养成习惯:服务器出问题时先跑诊断脚本保存现场,再开始排查。现场数据是最宝贵的线索。