Linux 性能诊断速查手册

写在前面

本文整理了 Linux 系统性能排查的常用命令和思路,涵盖 CPU、内存、磁盘、网络四大方向。按照"先定位问题方向,再深入排查"的逻辑组织,方便遇到性能问题时快速入手。


一、排查思路总览

遇到性能问题时,建议按以下顺序定位:

1
2
3
4
5
6
7
1. top / htop — 快速看全局,确认是 CPU、内存、还是 I/O 问题
2. 针对性深入排查:
   - CPU 高 → 进程级别分析(第三章)
   - 内存高 → 内存分配分析(第四章)
   - 磁盘慢 → I/O 分析(第五章)
   - 网络慢 → 网络分析(第六章)
3. 结合日志和监控确认根因

二、全局概览

2.1 top — 系统资源总览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 实时查看系统资源使用情况
top

# 常用交互操作:
# P — 按 CPU 排序
# M — 按内存排序
# 1 — 展开显示每个 CPU 核心
# c — 显示完整命令行
# k — 终止指定进程(输入 PID)
# q — 退出

关键字段解读:

1
2
3
4
5
6
7
8
top - 14:30:01 up 30 days,  3:20,  2 users,  load average: 2.5, 1.8, 1.2
#       当前时间     运行时间   用户数     负载均值(1分钟/5分钟/15分钟)

%Cpu(s): 25.0 us,  3.0 sy,  0.0 ni, 70.0 id,  1.5 wa,  0.5 si
#         用户态      内核态             空闲      I/O等待  软中断

MiB Mem :   7823.0 total,    256.0 free,   4096.0 used,   3471.0 buff/cache
#          总内存         空闲            已使用        缓冲/缓存

load average:三个数字分别表示过去 1、5、15 分钟的平均负载。数值接近 CPU 核心数时系统满载,超过则有过载。比如 4 核机器,load 到 4 就是满载。

wa(iowait):持续高于 5% 说明磁盘 I/O 是瓶颈。

2.2 htop — 增强版 top

1
2
3
4
# 更直观的资源监控(需安装)
htop

# 优势:支持鼠标、颜色区分、快捷键更友好、可直接看到每个核心使用率

2.3 uptime — 快速看负载

1
2
3
# 一行输出系统运行时间和负载
uptime
# 14:30:01 up 30 days,  3:20, 2 users, load average: 2.5, 1.8, 1.2

2.4 vmstat — 系统活动统计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 每隔2秒采样一次,共采5次
vmstat 2 5

# 关键列:
# r    — 运行队列中的进程数(持续大于 CPU 核心数说明 CPU 瓶颈)
# b    — 等待 I/O 的进程数(持续大于 0 说明 I/O 瓶颈)
# swpd — 已使用的 swap 大小(持续增长说明内存不够)
# si   — 每秒从 swap 读入内存(swap in)
# so   — 每秒从内存写入 swap(swap out)
# bi   — 每秒从磁盘读入的块数
# bo   — 每秒写入磁盘的块数
# us   — 用户态 CPU 时间百分比
# sy   — 内核态 CPU 时间百分比
# id   — 空闲 CPU 时间百分比
# wa   — I/O 等待时间百分比

三、CPU 排查

3.1 定位高 CPU 进程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 按CPU使用率排序,显示前10个进程
ps aux --sort=-%cpu | head -10

# 或者用 top 的批处理模式(适合脚本采集)
top -b -n 1 | head -20

# 查看指定进程的线程CPU占用
top -H -p <PID>

# 查看进程的所有线程
ps -T -p <PID>

3.2 分析进程在做什么

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看进程的系统调用(跟踪进程在干什么)
strace -p <PID> -c
# -c 会统计每种系统调用的次数和耗时,Ctrl+C 后输出汇总

# 实时跟踪进程的系统调用
strace -p <PID>

# 跟踪进程并统计耗时排序
strace -p <PID> -c -S time

# 只跟踪网络相关的系统调用
strace -p <PID> -e trace=network

3.3 perf — 性能分析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 对指定进程做 CPU profiling(采样10秒)
sudo perf top -p <PID>

# 记录性能数据
sudo perf record -p <PID> -g -- sleep 10

# 查看记录的性能报告
sudo perf report

# 查看系统全局的热点函数
sudo perf top

3.4 常见 CPU 高的原因

1
2
3
4
计算密集型业务 → 正常,考虑优化算法或扩容
频繁 GC       → java 应用的常见问题,查看 GC 日志
死循环        → 代码 bug,用 strace/perf 定位
上下文切换多  → 线程数过多,用 vmstat 看 cs 列

3.5 查看上下文切换

1
2
3
4
5
6
7
8
# 查看每秒上下文切换次数
vmstat 1 5
# 看 cs 列(context switch)

# 查看进程级别的自愿/非自愿上下文切换
pidstat -w 1 5
# cswch/s  — 自愿上下文切换(主动让出 CPU)
# nvcswch/s — 非自愿上下文切换(被内核抢占,说明 CPU 竞争激烈)

四、内存排查

4.1 查看内存使用

1
2
3
4
5
6
7
8
9
# 查看内存总览
free -h
#               total    used    free    shared  buff/cache   available
# Mem:         7.6Gi    4.0Gi   256Mi   16Mi     3.4Gi        3.2Gi
# Swap:        2.0Gi    512Mi   1.5Gi

# 重要:看 available 而不是 free
# available = 系统实际可用内存(包含可回收的缓存)
# free 只是完全未使用的内存,通常很少

buff/cache 是内核用作缓冲的内存,应用需要时会自动释放,不算"被占用"。

4.2 进程内存排名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 按内存使用率排序,显示前10
ps aux --sort=-%mem | head -10

# 查看指定进程的内存详情
cat /proc/<PID>/status | grep Vm
# VmRSS — 实际使用的物理内存(最常关注的)
# VmSize — 虚拟内存大小
# VmSwap — 使用的 swap 大小

# 查看进程内存映射
pmap -x <PID>

# 更直观的进程内存排序
smem -t -k -s rss    # 需安装 smem

4.3 查看 swap 使用情况

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看哪些进程在使用 swap
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
  swap=$(cat /proc/$pid/status 2>/dev/null | grep VmSwap | awk '{print $2}')
  if [ -n "$swap" ] && [ "$swap" -gt 0 ]; then
    name=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ')
    echo "PID: $pid  Swap: ${swap}kB  CMD: $name"
  fi
done | sort -k4 -rn | head -10

# 简化版:查看系统 swap 使用
swapon --show
cat /proc/swaps

4.4 slab 缓存分析

1
2
3
4
5
6
7
8
# 查看内核 slab 缓存占用
slabtop

# 查看内核内存使用概况
cat /proc/meminfo | grep -i slab
# Slab             — slab 缓存总量
# SReclaimable     — 可回收的 slab
# SUnreclaim       — 不可回收的 slab(持续增长需关注)

4.5 常见内存问题的排查方向

1
2
3
4
available 持续下降  → 内存泄漏,用 pmap 或应用工具定位
Swap 使用量高       → 物理内存不够,考虑加内存或优化进程
进程 RSS 异常大     → 检查是否有内存泄漏,查看 heap dump
系统 OOM Kill       → dmesg | grep -i oom 查看被杀的进程

4.6 OOM 日志查看

1
2
3
4
5
6
7
# 查看 OOM killer 记录
dmesg | grep -i "out of memory"
dmesg | grep -i "killed process"

# 从系统日志查看
grep -i "oom" /var/log/messages
journalctl -k | grep -i "oom"

五、磁盘 I/O 排查

5.1 iostat — 磁盘 I/O 统计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看所有磁盘的 I/O 统计(每秒刷新)
iostat -x 1

# 关键指标:
# %util  — 磁盘繁忙程度(接近 100% 说明磁盘饱和)
# await  — 平均 I/O 等待时间(ms),高于 10ms 需关注
# svctm  — 平均服务时间
# r/s    — 每秒读次数
# w/s    — 每秒写次数
# rkB/s  — 每秒读速度(KB)
# wkB/s  — 每秒写速度(KB)
# avgqu-sz — 平均 I/O 队列长度(持续大于 1 说明有积压)

await 持续高于 10ms%util 持续高于 80%,说明磁盘是瓶颈。

5.2 iotop — 查看哪个进程在疯狂读写磁盘

1
2
3
4
5
6
7
8
# 实时查看各进程的磁盘 I/O(需 root)
sudo iotop

# 只看有 I/O 活动的进程
sudo iotop -o

# 批处理模式(适合脚本采集)
sudo iotop -b -o -n 3

5.3 pidstat — 按进程查看 I/O

1
2
3
4
5
6
7
# 查看各进程的磁盘读写(每秒刷新)
pidstat -d 1

# 输出说明:
# kB_rd/s — 每秒读 KB
# kB_wr/s — 每秒写 KB
# kB_ccwr/s — 每秒取消写入的 KB

5.4 查看磁盘使用空间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看各磁盘使用率
df -h

# 查看目录大小
du -sh /var/log/*

# 找出最大的文件
find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh | head -20

# 查看inode使用率(inode满了也会报 No space left on device)
df -i

5.5 磁盘性能测试

1
2
3
4
5
6
7
8
9
# 测试顺序读速度
sudo hdparm -Tt /dev/sda

# 用 dd 测试写入速度(写一个 1GB 文件)
dd if=/dev/zero of=/tmp/testfile bs=1M count=1024 oflag=dsync
# 看输出中的速度,一般在 100MB/s 以上为正常(SSD 更高)

# 测试完成后删除测试文件
rm /tmp/testfile

5.6 常见磁盘问题

1
2
3
4
5
6
磁盘空间满        → df -h 定位,然后 du -sh * 找大文件
inode 满          → df -i 检查,通常是大量小文件导致
I/O wait 高       → iostat -x 1 看 %util 和 await
某个进程疯狂写盘   → iotop -o 定位进程
日志文件太大      → 用 logrotate 管理日志轮转
删除文件空间未释放 → lsof | grep deleted 查看,重启占用进程释放

5.7 查找已删除但未释放空间的文件

1
2
3
4
5
# 查看已删除但被进程占用未释放的文件
lsof | grep deleted

# 查看指定进程打开的文件
lsof -p <PID>

六、网络排查

6.1 网络连通性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 测试网络是否通
ping 8.8.8.8

# 测试指定端口是否通
telnet 192.168.1.100 8080
# 或
nc -zv 192.168.1.100 8080

# 测试到目标的网络路径和延迟
traceroute 8.8.8.8
# 或
mtr 8.8.8.8    # 持续版本的 traceroute(需安装)

6.2 mtr — 网络链路质量

1
2
3
4
5
6
7
8
# 持续探测到目标的每一跳
mtr --report baidu.com

# 关键指标:
# Loss%  — 丢包率(大于 0 需关注)
# Avg    — 平均延迟
# Worst  — 最差延迟
# StDev  — 延迟波动(越大越不稳定)

6.3 网卡流量与错误

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查看网卡流量
ip -s link show eth0

# 实时监控网卡流量(需安装)
iftop -i eth0

# 查看网卡统计信息(关注错误和丢包)
cat /proc/net/dev
# 关注:errors(错误数)、dropped(丢包数)

# 用 nload 看实时流量(需安装)
nload

6.4 TCP 连接统计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 查看所有 TCP 连接状态统计
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn

# 常见状态:
# ESTABLISHED  — 已建立的连接
# TIME_WAIT    — 等待关闭的连接(大量堆积需关注)
# CLOSE_WAIT   — 等待应用关闭的连接(大量堆积说明应用没正确关闭连接)
# SYN_SENT     — 正在建立连接(多说明连接慢或目标不可达)

# 查看连接数最多的 IP
ss -ant | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10

# 查看指定端口的连接数
ss -ant state established '( dport = :8080 or sport = :8080 )' | wc -l

6.5 sar — 网络历史统计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看历史网络流量(需安装 sysstat)
sar -n DEV

# 查看今天的网络流量,每秒刷新
sar -n DEV 1

# 查看 TCP 统计
sar -n TCP 1

# 查看 SOCK 统计(socket 使用情况)
sar -n SOCK 1

6.6 抓包分析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 抓取指定网卡的所有包
sudo tcpdump -i eth0

# 抓取指定端口的包
sudo tcpdump -i eth0 port 8080

# 抓取指定 IP 的包
sudo tcpdump -i eth0 host 192.168.1.100

# 抓取并保存到文件(用 Wireshark 分析)
sudo tcpdump -i eth0 -w capture.pcap

# 抓取指定端口的前 100 个包,显示内容
sudo tcpdump -i eth0 port 8080 -c 100 -A

# 组合过滤
sudo tcpdump -i eth0 host 192.168.1.100 and port 8080 -nn

6.7 curl 测量接口耗时

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 测量请求各阶段耗时
curl -o /dev/null -s -w "\
time_namelookup:  %{time_namelookup}s\n\
time_connect:     %{time_connect}s\n\
time_starttransfer: %{time_starttransfer}s\n\
time_total:       %{time_total}s\n\
http_code:        %{http_code}\n" https://example.com/api

# 各阶段含义:
# time_namelookup     — DNS 解析耗时
# time_connect        — TCP 连接耗时
# time_starttransfer  — 首字节到达耗时(含服务端处理)
# time_total          — 总耗时

# 判断依据:
# DNS 慢    → time_namelookup 高
# 网络慢    → time_connect 高
# 服务端慢  → time_starttransfer - time_connect 高
# 传输慢    → time_total - time_starttransfer 高

6.8 常见网络问题

1
2
3
4
5
6
连接超时        → 防火墙、路由、目标服务未启动
丢包严重        → mtr 逐跳排查,定位哪一跳开始丢包
TIME_WAIT 过多  → 短连接太多,考虑长连接或调整内核参数
CLOSE_WAIT 过多 → 应用没正确关闭连接,检查代码
带宽跑满        → iftop 定位哪个连接占用带宽
DNS 解析慢      → 换 DNS 或配置 /etc/hosts

七、综合排查场景

场景1:服务器响应变慢

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 第一步:快速全局查看
top
# 看 load average、%us、%sy、wa、内存

# 第二步:确认方向
vmstat 1 5
# r 列(运行队列)、wa(I/O等待)、swpd(swap使用)

# 第三步:根据方向深入
# CPU 高 → ps aux --sort=-%cpu | head -10
# 内存高 → free -h && ps aux --sort=-%mem | head -10
# 磁盘慢 → iostat -x 1
# 网络慢 → curl 测耗时,iftop 看流量

场景2:CPU 使用率突然飙高

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 找到占用 CPU 最高的进程
ps aux --sort=-%cpu | head -5

# 看这个进程的线程情况
top -H -p <PID>

# 跟踪进程在做什么
strace -p <PID> -c

# 如果是 Java 应用
jstack <PID> > thread_dump.txt
# 或者
jcmd <PID> Thread.print

场景3:应用频繁 OOM

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 查看 OOM 记录
dmesg | grep -i "killed process"

# 查看当前内存使用
free -h

# 找出内存占用最大的进程
ps aux --sort=-%mem | head -10

# 查看进程内存详情
pmap -x <PID>

# 如果是 Java 应用
jmap -heap <PID>
jmap -histo <PID> | head -20

场景4:磁盘 I/O 导致应用变慢

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 确认 I/O wait
top    # 看 wa 百分比
vmstat 1 5    # 看 wa 列和 b 列

# 查看哪个磁盘繁忙
iostat -x 1

# 找到疯狂读写磁盘的进程
sudo iotop -o

# 查看磁盘空间
df -h

场景5:网络请求慢

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 测试网络连通性和延迟
ping target-server
mtr target-server

# 测量接口各阶段耗时
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nFirstByte: %{time_starttransfer}s\nTotal: %{time_total}s\n" http://target-server/api

# 查看连接状态
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn

# 抓包分析
sudo tcpdump -i eth0 port 8080 -nn -c 100

八、常用工具速查

按场景选工具

场景 首选命令 辅助命令
快速全局查看 top / htop vmstat、uptime
CPU 高 ps、top -H strace、perf、pidstat
内存高 free、ps pmap、slabtop
磁盘慢 iostat -x iotop、pidstat -d
网络慢 ping、mtr curl、iftop、tcpdump
查看进程详情 /proc/PID/* pmap、lsof
查看系统日志 dmesg journalctl、/var/log/*

工具安装

1
2
3
4
5
6
7
# CentOS / RHEL
sudo yum install -y sysstat iotop htop iftop nload mtr

# Ubuntu / Debian
sudo apt install -y sysstat iotop htop iftop nload mtr-tiny

# sysstat 包含:iostat、mpstat、pidstat、sar