首页 Linux教程Linux 系统变慢?用这 8 个命令快速定位瓶颈

Linux 系统变慢?用这 8 个命令快速定位瓶颈

运维派隶属马哥教育旗下专业运维社区,是国内成立最早的IT运维技术社区,欢迎关注公众号:yunweipai
领取学习更多免费Linux云计算、Python、Docker、K8s教程关注公众号:马哥linux运维

一、问题背景

“系统变慢了”是运维群里出现频率最高的一句话。来源可能是用户、业务方、监控告警、值班人员。症状也很杂:网页打开慢、SSH 上去操作卡、SQL 查询慢、视频卡顿、定时任务跑不完、K8s Pod 频繁 OOM。

但”慢”本身不是结论,是一个症状。要解决它,必须先知道”慢在哪里”。常见瓶颈分布在四层:

  1. CPU 层:进程占用过高、上下文切换过载、软中断打满、单线程跑满核;
  2. 内存层:可用内存耗尽、swap 飙升、OOM 杀进程、page cache 抖动;
  3. IO 层:磁盘 await 飙升、IO 队列堆积、inode 耗尽、fd 耗尽、日志写爆盘;
  4. 网络层:带宽打满、丢包、重传、连接数耗尽、DNS 解析慢、TIME_WAIT 堆积。

每一层的检查工具、关键指标、典型场景都不一样。但大多数运维同学遇到”系统慢”时,第一反应往往就是登录服务器看 toptop 看了半天也没找到问题根源,时间一两个小时过去了,业务受损还在持续。

这篇文章把”系统慢”的标准排查路径沉淀成一套固定的命令组合。8 个核心命令 + 8 个进阶命令 + 完整的排查流程 + 真实场景示例,对照着做,目标是把首次定位时间从 30 分钟压缩到 5 分钟

写作思路:

  • 不讲大段理论,直接给命令、给指标、给判断逻辑;
  • 每个命令给出:目的、用法、预期输出、异常信号、下一步动作;
  • 把常见 6 类瓶颈场景分别给出排查案例;
  • 强调”先观察再动手”,所有修复操作必须可回滚。

二、适用场景

本文适用:

  1. 用户反馈”系统变慢”,但没有给出具体症状,需要快速定位瓶颈;
  2. 监控告警:load average 高、CPU 使用率高、内存使用率高、磁盘使用率高、网络流量异常;
  3. 应用日志出现超时(read timeout、connection timeout、request timeout);
  4. 业务请求 P99 / P95 突增,怀疑系统层问题;
  5. SSH 登录后操作卡顿(命令返回慢、history 加载慢);
  6. 定时任务跑不完(cron / systemd timer);
  7. K8s Pod 频繁 OOM Killed、Pending、NotReady;
  8. 数据库(MySQL/Redis/PG)慢查询,但怀疑不是数据库本身问题;
  9. Web 服务器(Nginx/Apache)出现 502/504,怀疑系统层问题;
  10. 容器宿主机负载异常,怀疑容器或宿主机问题。

不适用:

  • 应用代码 bug(死循环、内存泄漏)——本文聚焦 OS 层;
  • 网络层(L4 防火墙、交换机、运营商)问题——需要走网络排障流程;
  • 机房级故障(断电、空调)——走基础设施应急流程;
  • 硬件故障(磁盘坏道、内存故障)——需要走硬件更换流程。

三、核心知识点

3.1 性能分析的方法论

USE 方法(Brendan Gregg):

  • Utilization(利用率):资源有多忙;
  • Saturation(饱和度):资源排队的程度;
  • Errors(错误):错误事件的计数。

应用到这个场景:

  • CPU:利用率、运行队列长度、上下文切换、软中断;
  • 内存:利用率、可用内存、swap、page fault;
  • 磁盘:利用率、队列长度、await、服务时间;
  • 网络:带宽利用率、丢包率、连接数。

RED 方法:

  • Rate:每秒请求数;
  • Errors:每秒错误数;
  • Duration:每个请求的耗时。

应用到这个场景:

  • 应用 QPS、错误率、P99 延迟。

3.2 load average 的含义

load average 是衡量 Linux 系统负载的核心指标,定义是单位时间内处于可运行状态和不可中断睡眠状态的平均进程数

  • 可运行(R):正在使用 CPU 或等待 CPU;
  • 不可中断睡眠(D):正在等待 IO(通常是磁盘 IO)。

uptime 输出示例:

   14:30:01 up 100 days, 23:15,  1 user,  load average: 4.50, 5.20, 4.80

三个数字分别是 1 分钟、5 分钟、15 分钟的平均负载。

判断标准:

  • 与 CPU 核数对比:4 核 CPU,load 4 说明满载,load 16 说明严重排队;
  • 经验值:长期 load < 0.7 * CPU 核数算健康,> 1.0 * 核数说明有问题,> 2.0 * 核数说明严重排队;
  • 但要注意:CPU idle 90%、load 20 也是可能的(IO wait 导致)。

3.3 CPU 维度

CPU 状态分类(top / mpstat):

  • us:用户态(用户进程占用);
  • sy:内核态(系统调用、内核线程);
  • ni:nice 值调整后的用户态;
  • id:空闲;
  • wa:IO wait,等待 IO 完成;
  • hi:硬中断;
  • si:软中断;
  • st:被其他虚拟机偷走(云环境)。

判断逻辑:

  • us 高 + id 低:业务进程占用 CPU 严重;
  • sy 高:内核态繁忙,可能系统调用过多(高频 write、mmap、epoll);
  • wa 高:IO 瓶颈(磁盘/网络);
  • si 高:软中断打满(网卡、磁盘);
  • hi 高:硬件中断;
  • st 高:宿主机/邻居 VM 抢占(云环境)。

3.4 内存维度

free -h 输出:

                 total        used        free      shared  buff/cache   available
Mem:           15Gi        8.2Gi       1.2Gi       0.0Ki       6.0Gi       6.5Gi
Swap:         4.0Gi       1.5Gi       2.5Gi

关键指标:

  • total:物理内存总大小;
  • used:已用(不含 buffer/cache);
  • free:完全空闲;
  • buff/cache:buffer + page cache(可回收);
  • available:可用内存(含可回收);
  • Swap:swap 总量 + 已用。

判断逻辑:

  • available 接近 0:内存紧张;
  • swap 持续上涨:内存不足,触发 swap;
  • buff/cache 很大但 free 很小:正常,Linux 会用空闲内存做缓存;
  • si/so(swap in/out)持续非 0:swap 抖动,性能下降。

3.5 IO 维度

磁盘 IO 是最容易被忽视的瓶颈。iostat 关键指标:

   Device   r/s     w/s   rkB/s    wkB/s  await r_await w_await %util
sda      10      50    500      2000   30    5       35      95
  • r/sw/s:每秒读写次数(IOPS);
  • rkB/swkB/s:每秒读写带宽;
  • await:平均每次 IO 耗时(毫秒),含队列等待;
  • r_awaitw_await:读、写分别的 await;
  • %util:设备繁忙度,100% 表示饱和。

机械盘 vs SSD:

  • 机械盘:IOPS < 200,await 期望 < 10ms,%util 长期 > 80% 说明饱和;
  • SSD:IOPS 上万,await 期望 < 1ms,%util 不是判断标准,要看 await。

3.6 网络维度

关键指标:

  • 带宽利用率:sar -n DEV 1iftopnethogs
  • 丢包率:netstat -s 中的 segments retransmitted
  • 连接数:ss -sss -ant | wc -l
  • TIME_WAIT:ss -ant state time-wait | wc -l
  • CLOSE_WAIT:ss -ant state close-wait | wc -l
  • 软中断:cat /proc/net/softnet_stat

判断逻辑:

  • 带宽打满:业务流量超过网卡带宽(10Gbps / 1Gbps);
  • 丢包:物理链路、网卡驱动、内核参数都可能;
  • TIME_WAIT 多:短连接多,需要调整内核参数或开启 TIME_WAIT 复用;
  • CLOSE_WAIT 多:应用没正常关闭 socket,可能有 bug;
  • softnet_stat 第二列很大:软中断处理不及时,需要增加队列或 RSS。

3.7 文件系统维度

  • inode 耗尽:df -i
  • fd 耗尽:cat /proc/sys/fs/file-nr
  • 文件系统只读:dmesg 中 Read-only filesystem
  • LVM / mount 问题:mountdf -h

3.8 进程维度

pspidstattop 看进程状态:

  • R:运行中;
  • S:可中断睡眠;
  • D:不可中断睡眠(IO 等待);
  • Z:僵尸(父进程没回收);
  • T:停止;
  • I:空闲内核线程。

D 状态进程长时间存在是危险信号(可能是 IO hang 或内核 bug)。

3.9 内核参数

/etc/sysctl.conf 中的关键参数:

  • vm.swappiness:swap 倾向,0-100,默认 60,云主机常用 10;
  • net.core.somaxconn:listen backlog;
  • net.ipv4.tcp_max_syn_backlog:SYN 队列长度;
  • net.ipv4.tcp_tw_reuse:TIME_WAIT 复用;
  • net.ipv4.tcp_fin_timeout:FIN_WAIT_2 超时;
  • net.core.rmem_default/wmem_default:socket 缓冲区默认大小;
  • fs.file-max:系统最大 fd;
  • fs.nr_open:单进程最大 fd。

3.10 工具生态

   经典工具:top, vmstat, iostat, free, df, du, ss, netstat, ps, lsof
进阶工具:htop, iotop, iftop, nethogs, pidstat, mpstat, perf, strace, ltrace
高级工具:bpftrace, systemtap, ebpf, perf + FlameGraph
可视化:netdata, prometheus + grafana, zabbix

四、整体排查或实施思路

“系统慢”的标准排查路径分四层,由外到内、由系统到进程:

第一层:系统全局指标(30 秒)

目的:快速判断瓶颈在 CPU / 内存 / 磁盘 / 网络哪一层。

   bashuptime              # load average
top -bn1 | head -20 # CPU、内存、进程
free -h             # 内存
df -h               # 磁盘
ss -s               # 网络连接总数
dmesg -T | tail -30 # 内核报错

第二层:单维度深入(1-3 分钟)

针对第一层发现的瓶颈,进入对应维度深挖:

  • CPU 高 → mpstat -P ALL 1 5pidstat -u 1 5top -c
  • 内存高 → vmstat 1 5sar -r 1cat /proc/meminfo
  • IO 高 → iostat -xz 1 5iotoppidstat -d 1 5
  • 网络高 → sar -n DEV 1iftopnethogsss -antp

第三层:进程维度定位(3-5 分钟)

找到可疑进程后,深入分析:

  • pidstat -p PID -u -r -d 1 5:CPU/内存/IO;
  • cat /proc/PID/status:状态;
  • cat /proc/PID/limits:资源限制;
  • ls -l /proc/PID/fd | wc -l:fd 数量;
  • pmap -x PID:内存映射;
  • perf top -p PID:CPU 热点;
  • strace -p PID:系统调用;
  • lsof -p PID:打开的文件和连接。

第四层:修复与验证(5-15 分钟)

  • 应急处置:杀进程、限流、扩容;
  • 配置优化:内核参数、应用参数;
  • 验证:观察指标回归到基线。

排查路径速查表

   load 高 → CPU 高?wa 高?
  ├── CPU 高 → 哪个进程?→ perf top / strace
  ├── wa 高 → IO 高?→ iostat -xz
  └── sy 高 → 系统调用?→ strace / perf

内存高 → 哪个进程?
  ├── 单进程内存大 → pmap / heap dump
  ├── 频繁 OOM → dmesg OOM / cgroup 限制
  └── swap 高 → vmstat / sar -r

IO 高 → 哪个设备?
  ├── %util 高 + await 高 → 磁盘饱和
  ├── await 高但 %util 低 → 队列深度问题
  └── IOPS 高 → 应用 IO 模式问题

网络高 → 哪个连接?
  ├── 带宽满 → iftop / nethogs
  ├── 连接数满 → fd / somaxconn
  ├── 丢包 → netstat -s / dmesg
  └── DNS 慢 → systemd-resolved / dig

进程异常 → D 状态?fd 满?
  ├── D 状态多 → IO hang → dmesg / iostat
  ├── fd 满 → lsof + 调整 ulimit
  └── CPU 100% 单线程 → 应用 bug

五、实战步骤

5.1 步骤一:系统全局快查(30 秒)

目的:用 6 个命令快速判断瓶颈层。

   bash# 1. load average 与运行时长
uptime
# 输出:14:30:01 up 100 days, 23:15, 1 user, load average: 4.50, 5.20, 4.80

# 2. CPU、内存、进程 TOP
top -bn1 | head -20

# 3. 内存详情
free -h

# 4. 磁盘使用
df -h
df -i

# 5. 网络连接统计
ss -s

# 6. 内核报错
dmesg -T | tail -30

预期输出:

  • load 接近或超过 CPU 核数:CPU 瓶颈;
  • free 中 available 接近 0:内存瓶颈;
  • 磁盘使用 > 90%:磁盘满;
  • dmesg 出现 OOMIO errorsegfault:内核级问题。

异常表现:

  • load 高但 CPU idle 高 → IO wait 高(磁盘/网络瓶颈);
  • 内存 available 0 + swap 高 → 内存瓶颈;
  • df 显示 100% + 业务日志写失败 → 磁盘满;
  • dmesg 有 TCP: out of memory → 端口/socket 耗尽。

下一步动作:

  • 锁定瓶颈层后,进入对应维度的深入排查。

5.2 步骤二:CPU 维度深入

   bash# 1. 每个 CPU 核心的状态
mpstat -P ALL 1 5

# 2. 进程级 CPU
pidstat -u 1 5

# 3. top 找占用高的进程
top -c -b -n 1 | head -30

# 4. 按 CPU 排序的进程
ps -eo pid,ppid,user,pcpu,pmem,etime,args --sort=-pcpu | head -20

# 5. 单进程的 CPU 热点
top -Hp <PID>
perf top -p <PID>

# 6. 上下文切换与中断
vmstat 1 5
cat /proc/interrupts | head -20

# 7. 软中断
cat /proc/softirqs
mpstat -I ALL 1 5

# 8. 运行队列与负载
sar -q 1 5

# 9. CPU 频率
cat /proc/cpuinfo | grep "cpu MHz"
lscpu

# 10. 单进程系统调用
strace -p <PID> -c -f
strace -p <PID> -e trace=network,write,read

预期输出:

  • mpstat 显示每个核的 usr/sys/iowait/idle
  • pidstat 显示每个进程的 %user%system%guest%wait
  • vmstat 输出 procs r b 表示运行中和不可中断进程数。

判断逻辑:

  • 单核 usr > 80%:单进程占满核;
  • 单核 iowait > 30%:IO 等待;
  • procs r > CPU 核数:进程排队;
  • procs b > 0:不可中断睡眠;
  • system cs(context switch) > 100k/s:上下文切换过高;
  • system in(interrupt) > 10k/s:中断过高。

异常表现:

  • usr 95%+:单进程占满 CPU;
  • sy 30%+:内核态繁忙,可能是高频系统调用;
  • wa 30%+:IO 等待;
  • si 30%+:软中断,常见于网卡打爆;
  • cs > 100k:上下文切换频繁;
  • migration 大量:CPU 亲和性问题。

下一步动作:

  • 单进程占满 → 找到该进程,进一步分析;
  • sy 高 → strace 找热点 syscall;
  • si 高 → 找软中断来源(网卡/磁盘);
  • wa 高 → 进入 IO 维度排查。

5.3 步骤三:内存维度深入

   bash# 1. 内存详情
free -h
cat /proc/meminfo

# 2. 内存历史
vmstat 1 5
sar -r 1 5

# 3. swap 活动
vmstat 1 5
sar -S 1 5

# 4. OOM 历史
dmesg -T | grep -i "out of memory"
grep -i "oom" /var/log/messages
journalctl -k | grep -i "oom"

# 5. 大内存进程
ps -eo pid,ppid,user,pcpu,pmem,rss,vsz,args --sort=-rss | head -20

# 6. 单进程内存映射
pmap -x <PID> | sort -k3 -n -r | head

# 7. 详细内存使用
cat /proc/<PID>/smaps_rollup

# 8. 内存泄漏检测
valgrind --tool=massif --pages-as-heap=yes ./program

# 9. slab 缓存
slabtop
cat /proc/slabinfo

# 10. page cache 与 buffer
cat /proc/meminfo | grep -E "Buffers|Cached|SwapTotal|SwapFree"

# 11. cgroup 限制
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/memory.usage_in_bytes
cat /sys/fs/cgroup/memory/memory.failcnt

预期输出:

  • free -h:total/used/free/shared/buff/cache/available;
  • vmstat:si/so 表示 swap in/out;
  • pmap:进程虚拟内存映射;
  • cgroup:容器限制。

判断逻辑:

  • available < total * 10%:内存紧张;
  • si/so > 0:swap 抖动;
  • OOM 出现:触发 OOM Killer;
  • cache 占用多:正常,Linux 会用空闲内存做缓存;
  • slab 占用大:内核对象多(如 dentry、inode);
  • cgroup failcnt > 0:触发过 cgroup 限制。

异常表现:

  • swap 持续上涨:内存不足;
  • OOM 频繁:内存泄漏或限制过小;
  • 单进程 RSS > total/2:单进程内存占用过大;
  • dentry 或 inode cache 大:文件系统压力;
  • nfs_* cache 大:NFS 缓存占用。

下一步动作:

  • 单进程内存大 → pmap 进一步分析;
  • swap 高 → 找占用内存最多的进程或调 vm.swappiness
  • OOM → 调大内存或调小 cgroup 限制;
  • 内存泄漏 → heap dump + 分析。

5.4 步骤四:磁盘 IO 维度深入

   bash# 1. 系统级 IO
vmstat 1 5
# 看 bi/bo(block in/out)

# 2. 每个磁盘的 IO
iostat -xz 1 5
iostat -xz -m 1 5

# 3. 按进程统计 IO
iotop -o -P -d 5

# 4. 进程级 IO
pidstat -d 1 5

# 5. 读写的文件
lsof -p <PID> | grep -E "REG|DIR"

# 6. 大文件查找
find / -size +100M -type f 2>/dev/null | head -20
find / -size +1G -type f 2>/dev/null

# 7. 目录大小
du -sh /var/log/*
du -sh /var/lib/*

# 8. 排查删除但未释放的文件
lsof | grep deleted

# 9. 写日志最多的进程
lsof | awk '$5 == "REG" && $4 == "w" {print}' | head

# 10. 块设备队列
cat /sys/block/sda/queue/nr_requests
cat /sys/block/sda/queue/scheduler

# 11. 块设备统计
cat /proc/diskstats

# 12. IO 跟踪
iotop -p <PID>
strace -p <PID> -e trace=read,write,preadv,pwritev -c

预期输出:

  • iostat 输出每个设备的 r/s、w/s、rkB/s、wkB/s、await、%util;
  • iotop 按进程 IO 排序;
  • pidstat -d 显示每个进程的 read/write/swap。

判断逻辑:

  • %util 接近 100%:设备饱和;
  • await 远高于设备服务时间:队列堆积;
  • r/s + w/s 接近设备 IOPS 上限:IOPS 满;
  • rkB/s + wkB/s 接近设备带宽:带宽满;
  • iostat 中 svctm(服务时间)较大:设备本身慢。

异常表现:

  • 机械盘 %util 长期 > 80%:磁盘 IO 饱和;
  • SSD await > 10ms:SSD 性能问题;
  • 单进程 IO 很高:业务 IO 模式问题;
  • find / 占用大量 IO:定时任务撞 IO;
  • 大量 deleted 文件未释放:日志句柄没关。

下一步动作:

  • 找到 IO 高的进程,分析 IO 模式;
  • 大文件清理;
  • 调整 IO 调度器(deadline、noop、cfq);
  • 限流(ionice、cgroup blkio)。

5.5 步骤五:网络维度深入

   bash# 1. 网卡流量
sar -n DEV 1 5
iftop -i eth0

# 2. 按进程统计流量
nethogs -d 5

# 3. TCP/UDP 连接统计
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c

# 4. TIME_WAIT / CLOSE_WAIT
ss -ant state time-wait | wc -l
ss -ant state close-wait | wc -l
ss -ant state established | wc -l

# 5. 按进程统计 ESTABLISHED
ss -antp state established | grep -E "users:" | awk '{for(i=1;i<=NF;i++) if($i~/users:/) print $(i+1)}' | sort | uniq -c | sort -rn | head

# 6. 网络协议统计
netstat -s
ss -s

# 7. 丢包与重传
netstat -s | grep -E "retransmit|drop|timeout"
cat /proc/net/softnet_stat

# 8. 网卡中断
cat /proc/interrupts | grep eth0
watch -n 1 "cat /proc/interrupts | grep eth0"

# 9. 抓包
tcpdump -i eth0 -nn -s0 -w capture.pcap
tcpdump -i eth0 -nn port 80

# 10. DNS 解析时间
dig +stats example.com

# 11. traceroute / mtr
mtr -rwc 30 example.com

# 12. 内核网络参数
sysctl -a | grep -E "net\.(core|ipv4)"

预期输出:

  • sar -n DEV:每秒收发的 KB/s;
  • iftop:实时流量;
  • ss -s:连接总数 + 各状态分布;
  • softnet_stat:每个 CPU 队列的处理情况。

判断逻辑:

  • 带宽满:网卡 rxkB/s + txkB/s 接近网卡最大带宽;
  • 丢包:/proc/net/softnet_stat 第二列很大;
  • TIME_WAIT 多:短连接多;
  • CLOSE_WAIT 多:应用 bug;
  • retransmit 多:网络质量差或 server 端慢;
  • DNS 慢:resolver 配置或上游 DNS 问题。

异常表现:

  • 10Gbps 网卡跑满:业务流量大;
  • 1Gbps 网卡跑满:业务流量超过设计容量;
  • CLOSE_WAIT 持续上涨:业务没正常关闭连接;
  • TIME_WAIT 涨到几十万:短连接服务需要内核参数优化;
  • 软中断单核 100%:网卡 RSS 没配。

下一步动作:

  • 带宽满 → 扩容或限流;
  • 丢包 → 排查网络设备;
  • TIME_WAIT 多 → 调整内核参数(tcp_tw_reusetcp_tw_recycle);
  • CLOSE_WAIT 多 → 应用排查;
  • DNS 慢 → 换 DNS server。

5.6 步骤六:进程维度深挖

   bash# 1. 进程状态
ps -eo pid,user,stat,etime,pcpu,pmem,args | head -20

# 2. 进程 /proc/<PID>/ 详细信息
PID=12345
cat /proc/$PID/status
cat /proc/$PID/stat
cat /proc/$PID/cmdline
ls -la /proc/$PID/exe
ls -la /proc/$PID/cwd
ls -la /proc/$PID/fd | wc -l
cat /proc/$PID/limits
cat /proc/$PID/smaps_rollup

# 3. 进程打开的文件
lsof -p $PID | head -30
lsof -p $PID | grep -E "REG|DIR|sock"
lsof -p $PID | grep -E "REG.*deleted"

# 4. 进程的网络连接
ss -antp | grep $PID

# 5. 进程的环境变量
cat /proc/$PID/environ | tr'\0''\n'

# 6. 进程的资源占用
pidstat -p $PID -u -r -d 1 5

# 7. CPU 热点
perf top -p $PID
perf record -p $PID -g -- sleep 10
perf report

# 8. 系统调用热点
strace -p $PID -c
strace -p $PID -e trace=network,read,write -c

# 9. 进程关联的内核调用
cat /proc/$PID/wchan
cat /proc/$PID/syscall

# 10. 子进程
ps --ppid $PID

# 11. 线程
ps -eLf | grep $PID | head
cat /proc/$PID/status | grep Threads

# 12. 进程优先级
chrt -p $PID
cat /proc/$PID/stat | awk '{print "priority="$18,"nice="$19}'

预期输出:

  • /proc/PID/statusStateVmRSSThreadsvoluntary_ctxt_switches 等;
  • lsof:进程打开的文件、socket;
  • perf top:CPU 热点函数;
  • strace -c:系统调用统计。

判断逻辑:

  • 进程 State 为 D:IO 等待,需要看 wchan
  • Threads 过大:线程数过多;
  • fd 数量接近 ulimit -n:fd 耗尽风险;
  • VmRSS 大:内存占用大;
  • voluntary_ctxt_switches 高:进程主动让出 CPU;
  • nonvoluntary_ctxt_switches 高:被调度器抢。

异常表现:

  • 进程 D 状态长时间:IO hang;
  • fd 数 > 10000:可能 fd 泄漏;
  • 单进程 100+ 线程:可能线程泄漏;
  • perf top 显示某函数占用高:CPU 热点定位;
  • strace 显示某 syscall 频繁:系统调用热点。

下一步动作:

  • D 状态:找 IO 根因(磁盘/网络);
  • fd 泄漏:调大 ulimit 或修 bug;
  • 线程泄漏:调小或修 bug;
  • CPU 热点:perf + FlameGraph 分析;
  • syscall 热点:调小 syscall 频率或换更高效的调用。

5.7 步骤七:常见瓶颈场景排查示例

场景 1:CPU 跑满

   bash# 现象
uptime
# load average: 24.50, 25.20, 24.80
# 4 核 CPU
top -bn1 | head -10
# %Cpu(s): 95.0 us,  2.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  3.0 si,  0.0 st

# 定位
ps -eo pid,pcpu,args --sort=-pcpu | head
# PID 12345 mysqld 占 800%

# 进一步分析
top -Hp 12345
# 看到 mysqld 多线程都忙
mysqladmin -u root -p processlist
# 看慢查询

# 修复
# 1. 找到慢 SQL,加索引或优化
# 2. 调小 innodb_thread_concurrency
# 3. 杀慢查询:KILL QUERY <thread_id>

场景 2:内存耗尽 + OOM

   bash# 现象
free -h
# available 0
# swap used 4G
dmesg -T | grep -i oom
# Out of memory: Killed process 12345 (java)

# 定位
ps -eo pid,user,rss,args --sort=-rss | head
# PID 12345 java RSS 32G

# 进一步分析
pmap -x 12345 | sort -k3 -n -r | head
# 看大块内存分配

# 修复
# 1. 调小 JVM heap
# 2. 重启进程
# 3. 排查内存泄漏

场景 3:磁盘 IO 满

   bash# 现象
iostat -xz 1 5
# sda await 200ms, %util 100%

# 定位
iotop -o -P
# PID 12345 mysqld 占 100M/s 写

# 进一步分析
lsof -p 12345 | grep REG
# 看写哪些文件

# 修复
# 1. 调小 innodb_io_capacity
# 2. 错峰执行大查询
# 3. 换 SSD

场景 4:磁盘写满

   bash# 现象
df -h
# /var 100%
业务报错:No space left on device

# 定位
du -sh /var/* | sort -h | tail
# /var/log/messages 占 200G

# 进一步分析
ls -la /var/log/messages
# 文件 200G
lsof | grep "/var/log/messages"
# 进程 PID 12345 占着

# 修复
# 1. 用 truncate 截断(不删文件,进程句柄仍可用)
truncate -s 0 /var/log/messages
# 2. 或 cat /dev/null > file(不删 inode)
# 3. 或 mv 文件后重启 rsyslog
# 不要 rm,会释放 inode,但进程还在写,可能出错

场景 5:网络连接耗尽

   bash# 现象
业务报错:Cannot assign requested address
ss -s
# TCP: 60000 (estab 50000, closed 8000, orphaned 0, timewait 1000)

# 定位
cat /proc/sys/net/ipv4/ip_local_port_range
# 32768 60999 = 28232 个端口

# 进一步分析
ss -antp | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head
# 看来源 IP 分布

# 修复
# 1. 调整端口范围
echo"net.ipv4.ip_local_port_range = 1024 65535" >> /etc/sysctl.conf
sysctl -p

# 2. 开启 TIME_WAIT 复用
echo"net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
sysctl -p

场景 6:fd 耗尽

   bash# 现象
业务报错:Too many open files
cat /proc/sys/fs/file-nr
# 16384 16384 65536

# 定位
ls -l /proc/<PID>/fd | wc -l
# 接近 ulimit -n

# 进一步分析
lsof -p <PID> | grep -E "REG|DIR" | awk '{print $NF}' | sort | uniq -c | sort -rn | head
# 看打开的文件分布

# 修复
# 1. 调大 ulimit
echo"ulimit -n 65535" >> /etc/security/limits.conf
# 2. 排查 fd 泄漏(用 lsof 看哪些 fd 不该开)

5.8 步骤八:应急处置

   bash# 1. 杀进程(先 STOP 留证据,再 TERM,最后 KILL)
kill -STOP <PID>       # 暂停进程,便于排查
kill -CONT <PID>       # 恢复进程
kill -TERM <PID>       # 优雅退出
sleep 5
kill -9 <PID>          # 强制 kill,慎用

# 2. 限流(用 ionice、cgroup)
ionice -c2 -n7 -p <PID>          # 调低 IO 优先级
renice +10 -p <PID>              # 调低 CPU 优先级

# 3. 隔离(用 cgroup)
mkdir -p /sys/fs/cgroup/cpu/test.slice
echo <PID> > /sys/fs/cgroup/cpu/test.slice/tasks
echo 100000 > /sys/fs/cgroup/cpu/test.slice/cpu.cfs_quota_us

# 4. 限速(tc / iptables)
iptables -I OUTPUT -p tcp --dport 80 -m limit --limit 100/s -j ACCEPT
iptables -I OUTPUT -p tcp --dport 80 -j DROP

# 5. 卸载磁盘(紧急)
umount /data   # 会影响正在使用该盘的业务

# 6. 紧急扩容(云环境)
# 走云厂商 API

# 7. 切流(CDN/GSLB)
# 走运维平台切流

# 8. 重启服务
systemctl restart <service>

5.9 步骤九:长期治理

   bash# 1. 容量规划(基于历史数据)
sar -u -r -d -n DEV -f /var/log/sa/sa$(date +%d -d yesterday)

# 2. 监控告警
# 部署 Prometheus + node_exporter + Grafana

# 3. 压测
wrk -t 10 -c 1000 -d 60s http://example.com
ab -n 100000 -c 1000 http://example.com/

# 4. 优化(应用/配置/架构)
# 应用:缓存、异步、批量
# 配置:内核参数、连接池
# 架构:读写分离、分库分表、CDN、缓存层

# 5. Runbook
# 把排查路径沉淀到 Runbook
# 把常见问题写成 FAQ
# 把应急流程做成 Ansible role

六、常用命令

6.1 综合快查

   bashuptime
top -bn1 | head -20
free -h
df -h
df -i
ss -s
dmesg -T | tail -30

6.2 CPU

   bashtop
htop
mpstat -P ALL 1 5
mpstat -I ALL 1 5
pidstat -u 1 5
vmstat 1 5
sar -u 1 5
perf top
perf record -g -p <PID> -- sleep 10 && perf report
strace -p <PID>
cat /proc/loadavg
cat /proc/cpuinfo
lscpu

6.3 内存

   bashfree -h
cat /proc/meminfo
vmstat 1 5
sar -r 1 5
sar -S 1 5
slabtop
dmesg | grep -i oom
ps -eo pid,user,rss,args --sort=-rss | head
pmap -x <PID>
cat /proc/<PID>/smaps_rollup
cat /proc/<PID>/status

6.4 IO

   bashiostat -xz 1 5
iostat -xz -m 1 5
iotop -o -P
pidstat -d 1 5
vmstat 1 5   # bi/bo
sar -d 1 5
lsof -p <PID> | grep REG
find / -size +1G -type f 2>/dev/null
du -sh /var/log/* | sort -h
lsof | grep deleted

6.5 网络

   bashsar -n DEV 1 5
sar -n EDEV 1 5
iftop -i eth0
nethogs -d 5
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c
ss -antp state established
netstat -s
cat /proc/net/softnet_stat
tcpdump -i eth0 -nn -s0 -w capture.pcap
mtr -rwc 30 example.com
dig +stats example.com

6.6 进程

   bashps auxf
ps -eo pid,ppid,user,pcpu,pmem,args --sort=-pcpu | head
top -Hp <PID>
pidstat -p <PID> -u -r -d 1 5
cat /proc/<PID>/status
cat /proc/<PID>/cmdline
ls -la /proc/<PID>/exe
ls -la /proc/<PID>/fd | wc -l
lsof -p <PID>
pstree -ap <PID>

6.7 内核

   bashsysctl -a
sysctl -p
cat /etc/sysctl.conf
uname -a
dmesg -T
journalctl -k

6.8 应急

   bashkill -STOP <PID>
kill -CONT <PID>
kill -TERM <PID>
kill -9 <PID>
renice +10 -p <PID>
ionice -c2 -n7 -p <PID>
systemctl restart <service>
iptables -I INPUT -s <ip> -j DROP
umount /data
swapoff /dev/sda2

七、配置示例

7.1 sysctl 内核参数调优(/etc/sysctl.conf

   conf# ---------- 内存 ----------
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 100

# ---------- 网络 ----------
net.core.somaxconn = 65535
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 65535

net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0   # 注意:4.12+ 已废弃
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_slow_start_after_idle = 0

net.ipv4.ip_local_port_range = 1024 65535

# ---------- 文件系统 ----------
fs.file-max = 2097152
fs.nr_open = 1048576
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 8192

# ---------- 内核 ----------
kernel.pid_max = 4194304
kernel.threads-max = 4194304
kernel.shmmax = 68719476736
kernel.shmall = 4294967296

# ---------- 容器/cgroup 相关 ----------
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

加载:

   bashsysctl -p

7.2 limits.conf(/etc/security/limits.conf

   conf# 系统全局
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535

# 特定用户
mysql soft nofile 65535
mysql hard nofile 65535
mysql soft nproc 65535
mysql hard nproc 65535

# root
root soft nofile 1048576
root hard nofile 1048576

7.3 Prometheus node_exporter 告警规则

   yamlgroups:
  -name:node_alerts
    rules:
      -alert:HighLoadAverage
        expr:node_load5>(countby(instance)(node_cpu_seconds_total{mode="idle"})*1.5)
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} 5 分钟 load 高于 CPU 核数 1.5 倍"

      -alert:HighCPUUsage
        expr:(1-avgby(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])))*100>80
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} CPU 使用率超过 80%"

      -alert:HighMemoryUsage
        expr:(1-(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes))*100>85
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} 内存使用率超过 85%"

      -alert:HighDiskUsage
        expr:(1-(node_filesystem_avail_bytes{fstype!="tmpfs"}/node_filesystem_size_bytes{fstype!="tmpfs"}))*100>85
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} {{ $labels.mountpoint }} 磁盘使用率超过 85%"

      -alert:HighDiskIO
        expr:rate(node_disk_io_time_seconds_total[5m])*100>80
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} 磁盘 {{ $labels.device }} IO 使用率超过 80%"

      -alert:DiskAwaitHigh
        expr:rate(node_disk_read_time_seconds_total[5m])/rate(node_disk_reads_completed_total[5m])>0.05
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} 磁盘 {{ $labels.device }} await 超过 50ms"

      -alert:HighNetworkTraffic
        expr:rate(node_network_receive_bytes_total{device!="lo"}[5m])*8>8000000000
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} 网络接收速率超过 8Gbps"

      -alert:HighConntrackUsage
        expr:node_nf_conntrack_entries/node_nf_conntrack_entries_limit*100>80
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} conntrack 表使用率超过 80%"

      -alert:OOMKilled
        expr:increase(node_vmstat_oom_kill[5m])>0
        for:0m
        labels:
          severity:critical
        annotations:
          summary:"{{ $labels.instance }} 发生 OOM"

      -alert:HighContextSwitch
        expr:rate(node_context_switches_total[5m])>100000
        for:5m
        labels:
          severity:warning
        annotations:
          summary:"{{ $labels.instance }} 上下文切换超过 10万/s"

7.4 自动化巡检脚本(/usr/local/bin/sys_health_check.sh

   bash#!/usr/bin/env bash
# 系统健康巡检
# 输出:/var/log/sys_health/$(hostname)-$(date +%F).log

LOG_DIR=/var/log/sys_health
LOG_FILE="$LOG_DIR/$(hostname)-$(date +%F).log"
mkdir -p "$LOG_DIR"

exec > >(tee -a "$LOG_FILE") 2>&1

echo"===== System Health Check ====="
echo"Time: $(date '+%F %T')"
echo"Hostname: $(hostname)"

echo"----- Uptime -----"
uptime

echo"----- CPU -----"
top -bn1 | head -10

echo"----- Memory -----"
free -h
echo"Swap info:"
cat /proc/meminfo | grep -E "SwapTotal|SwapFree"

echo"----- Disk -----"
df -h
df -i

echo"----- Disk IO -----"
iostat -xz 1 3 2>/dev/null || echo"iostat not installed"

echo"----- Network -----"
ss -s
echo"Established connections:"
ss -antp state established | head -20

echo"----- Top 10 CPU -----"
ps -eo pid,ppid,user,pcpu,pmem,etime,args --sort=-pcpu | head -10

echo"----- Top 10 Memory -----"
ps -eo pid,ppid,user,pcpu,pmem,rss,args --sort=-rss | head -10

echo"----- Top 10 IO -----"
pidstat -d 1 2 2>/dev/null | tail -20 || echo"pidstat not installed"

echo"----- OOM -----"
dmesg -T | grep -i "out of memory" | tail -5

echo"----- Load Average -----"
cat /proc/loadavg

echo"----- Conntrack -----"
cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null
cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null

echo"----- File Descriptor -----"
cat /proc/sys/fs/file-nr

echo"===== End ====="
   bashchmod +x /usr/local/bin/sys_health_check.sh

# 每天跑一次
cat > /etc/cron.d/sys_health <<'EOF'
0 8 * * * root /usr/local/bin/sys_health_check.sh
EOF

7.5 Grafana 面板 JSON(基础系统面板)

   json{
  "title":"Linux System Overview",
"panels":[
    {
      "title":"CPU Usage",
      "type":"graph",
      "targets":[
        {
          "expr":"1 - avg by(instance)(rate(node_cpu_seconds_total{mode=\"idle\"}[5m]))",
          "legendFormat":"{{instance}}"
        }
      ]
    },
    {
      "title":"Memory Usage",
      "type":"graph",
      "targets":[
        {
          "expr":"(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100",
          "legendFormat":"{{instance}}"
        }
      ]
    },
    {
      "title":"Load Average",
      "type":"graph",
      "targets":[
        {
          "expr":"node_load5",
          "legendFormat":"{{instance}} load5"
        }
      ]
    },
    {
      "title":"Disk Usage",
      "type":"graph",
      "targets":[
        {
          "expr":"(1 - (node_filesystem_avail_bytes{fstype!=\"tmpfs\"} / node_filesystem_size_bytes{fstype!=\"tmpfs\"})) * 100",
          "legendFormat":"{{instance}} {{mountpoint}}"
        }
      ]
    },
    {
      "title":"Disk IOPS",
      "type":"graph",
      "targets":[
        {
          "expr":"rate(node_disk_reads_completed_total[5m]) + rate(node_disk_writes_completed_total[5m])",
          "legendFormat":"{{instance}} {{device}}"
        }
      ]
    },
    {
      "title":"Network Traffic",
      "type":"graph",
      "targets":[
        {
          "expr":"rate(node_network_receive_bytes_total{device!=\"lo\"}[5m]) * 8",
          "legendFormat":"{{instance}} RX"
        },
        {
          "expr":"rate(node_network_transmit_bytes_total{device!=\"lo\"}[5m]) * 8",
          "legendFormat":"{{instance}} TX"
        }
      ]
    }
]
}

八、日志或指标观察方法

8.1 关键指标速查

维度指标命令健康基线(参考)异常信号
CPUload5uptime< 0.7 * 核数> 1.0 * 核数
CPUidle%top / mpstat> 20%< 10%
CPUiowait%top / mpstat< 10%> 30%
CPU上下文切换/svmstat< 50k> 100k
CPU中断/svmstat< 5k> 10k
内存available%free> 20%< 10%
内存swap usedfree接近 0持续上涨
内存OOMdmesg0> 0
磁盘%utiliostat< 70%> 90%
磁盘awaitiostat< 10ms(SSD < 1ms)> 30ms
磁盘空间%df< 80%> 90%
磁盘inode%df -i< 80%> 90%
网络带宽%sar -n DEV< 70%> 90%
网络TIME_WAITss< 10k> 50k
网络CLOSE_WAITss< 100> 1000
网络丢包率netstat -s极低> 1%
进程fd/proc/PID/fd< 1000> 10000
进程线程数ps< 100> 500
进程D 状态ps0> 0

8.2 重点日志

路径用途
/var/log/messages系统综合日志
/var/log/syslog (Debian)系统综合日志
/var/log/kern.log内核日志
/var/log/dmesg启动日志
/var/log/croncron 执行日志
journaldsystemd 日志
应用日志在 /var/log/<app>/ 或 /data/logs/

8.3 关键观察方法

  • vmstat 1 5:每秒采样 5 次,看趋势;
  • iostat -xz 1 5:磁盘每秒采样;
  • sar -u -r -d -n DEV 1 100:100 次采样,便于后续分析;
  • perf record/report:CPU 热点采样;
  • strace -p PID -c:系统调用采样;
  • tcpdump -w:网络抓包;
  • journalctl -k:内核日志;
  • ausearch:auditd 日志。

九、排查路径

9.1 排查路径速查表

现象第一动作关键命令进一步动作
系统整体慢看 loaduptimetopmpstat / iostat
CPU 100%找进程top -cps -eo --sort=-pcpuperf / strace
单核满找进程top -Hp PID单线程分析
内存满找进程ps -eo --sort=-rsspmap / heap dump
OOM看 dmesg`dmesggrep OOM`
磁盘满找大文件du -shfind -sizetruncate 或 mv
磁盘 IO 满找进程iotop调整应用 IO
inode 满找小文件`find -size -1k -type fwc -l`
fd 满找进程lsof -p调大 ulimit
网络慢看带宽sar -n DEViftop限流或扩容
丢包看统计netstat -s排查链路
DNS 慢看解析dig +stats换 DNS
TIME_WAIT 多调内核`sysctl -agrep tw`
CLOSE_WAIT 多找进程ss -antp修应用
SSH 卡顿看 loaduptimetop排查同主机其他进程

9.2 完整排查流程

   收到"系统慢"投诉
   ↓
[步骤 1] 全局快查(30 秒)
   ├── load 高?→ CPU/IO 维度
   ├── 内存满?→ 内存维度
   ├── 磁盘满?→ 磁盘维度
   └── 网络慢?→ 网络维度
   ↓
[步骤 2] 维度深入(1-3 分钟)
   ↓
[步骤 3] 进程定位(3-5 分钟)
   ↓
[步骤 4] 根因分析(5-10 分钟)
   ├── 应用 bug?
   ├── 配置不当?
   ├── 容量不足?
   └── 内核/硬件问题?
   ↓
[步骤 5] 应急处置(10-30 分钟)
   ├── 杀进程
   ├── 限流
   ├── 扩容
   └── 切流
   ↓
[步骤 6] 验证(持续观察)
   ├── 指标回归基线
   ├── 业务恢复
   └── 监控正常
   ↓
[步骤 7] 长期治理
   ├── 容量规划
   ├── 监控告警
   ├── 自动化运维
   └── 架构优化

十、风险提醒

10.1 杀进程风险

  • 不要在没确认进程归属前 kill;
  • kill -STOP 是安全的(暂停进程,便于排查);
  • kill -TERM 是优雅退出,进程会清理资源;
  • kill -9 跳过清理逻辑,可能导致共享内存泄漏、socket 没关闭;
  • kill -9 对数据库进程可能导致主从不一致;
  • kill -9 -1 会杀所有进程,等于 pkill -9 -P 1,慎用。

10.2 修改内核参数风险

  • sysctl -p 会立即生效,部分参数可能导致连接重置;
  • vm.swappiness 调到 0:内核只在紧急情况下 swap,可能 OOM;
  • vm.swappiness 调到 100:积极 swap,可能影响 IO;
  • tcp_tw_recycle 在 4.12+ 已废弃,开启可能导致 NAT 后面的客户端连不上;
  • 修改 ip_local_port_range 不要太小,会导致端口耗尽;
  • 修改 somaxconn 要配套修改应用 backlog;
  • 修改前必须 sysctl -a > backup.txt 备份。

10.3 修改数据库参数风险

  • 不要在排查系统慢时随意调数据库参数;
  • 数据库参数调整要走变更流程;
  • 调 innodb_buffer_pool_size 等大参数会触发重启;
  • 调 innodb_thread_concurrency 影响并发;
  • 调小 max_connections 会拒绝连接;
  • 调整 innodb_io_capacity 影响 IO 行为。

10.4 清理日志风险

  • 不要用 rm 删除正在写入的日志文件(虽然 inode 释放,但句柄仍占用);
  • 用 truncate -s 0 截断(保留 inode,进程继续写);
  • 用 cat /dev/null > file 清空(保留 inode);
  • mv 文件后让 rsyslog 重启生成新文件;
  • 关键日志清理前先归档;
  • 不要在 logrotate 配置错误时手动清理,会导致日志断层。

10.5 重启服务风险

  • 重启前必须评估影响范围;
  • 重启前必须通知相关方;
  • 重启前必须有回滚方案;
  • 重启前必须备份配置;
  • 数据库重启要走变更流程;
  • 关键服务要在低峰期重启。

10.6 批量脚本风险

  • 批量执行的脚本必须有 dry-run 模式;
  • 必须支持并发控制(-p 5);
  • 必须有超时控制;
  • 必须有失败中止逻辑;
  • 必须有日志输出;
  • 必须有异常通知;
  • 不要在生产环境无审阅执行 ansible all -m shell -a 'rm -rf /tmp/*'

10.7 数据迁移风险

  • 数据迁移前必须有备份;
  • 迁移后必须有验证;
  • 迁移过程中必须有校验;
  • 迁移失败必须能回滚;
  • 迁移期间必须有监控;
  • 跨主机迁移要注意带宽影响。

10.8 误判风险

  • 单核 100% 不一定是瓶颈,可能是单线程程序的正常行为;
  • load 高不一定是系统问题,可能是业务正常增长;
  • 内存占用高不一定是泄漏,可能是 Linux 的 page cache;
  • 磁盘 IO 高不一定是问题,可能是业务备份;
  • 网络流量高不一定是攻击,可能是业务;
  • 关键是要和业务基线对比,不要单看指标绝对值。

十一、验证方式

11.1 验证 CPU

   bash# 1. 实时看 CPU
top
htop
mpstat -P ALL 1 5

# 2. 看 CPU 热点是否消除
perf top -p <PID>
# 修复后应该没有 dominant 函数

# 3. 上下文切换是否下降
vmstat 1 5
# cs 列

# 4. 进程 CPU 占用是否下降
top -p <PID>
# %CPU 应该 < 50%

11.2 验证内存

   bash# 1. 看 available
free -h
# available 应该 > total * 20%

# 2. 看 swap 活动
vmstat 1 5
# si/so 应该接近 0

# 3. 看 OOM 是否停止
dmesg -T | grep -i oom
# 应该没有新 OOM

# 4. 看进程 RSS
ps -eo pid,rss,args --sort=-rss | head
# 内存占用应该稳定或下降

11.3 验证磁盘

   bash# 1. 看磁盘使用率
df -h
# 应该 < 80%

# 2. 看磁盘 IO
iostat -xz 1 5
# %util 应该 < 70%,await 应该正常

# 3. 看 inode
df -i
# 应该 < 80%

# 4. 看是否有 deleted 文件
lsof | grep deleted
# 应该没有大文件

11.4 验证网络

   bash# 1. 看带宽
sar -n DEV 1 5
# rxkB/s + txkB/s 应该 < 带宽 * 70%

# 2. 看连接数
ss -s
# 各状态连接数应该稳定

# 3. 看 TIME_WAIT
ss -ant state time-wait | wc -l
# 应该 < 10k

# 4. 看丢包
netstat -s | grep retransmit
# 应该没有增长

# 5. 业务连通性
curl -v -m 5 http://example.com/
nc -vz example.com 80

11.5 验证业务

   bash# 1. 应用日志
tail -f /var/log/app/app.log
# 应该没有 timeout、error

# 2. 监控告警
# 应该没有 critical 告警

# 3. 用户反馈
# 通过客服、工单、用户群确认恢复

# 4. 关键指标
# P99 延迟、错误率、QPS 回归基线

11.6 验证内核参数

   bash# 看参数是否生效
sysctl net.core.somaxconn
sysctl vm.swappiness

# 看进程 ulimit
cat /proc/<PID>/limits | grep "open files"

# 看文件描述符
cat /proc/sys/fs/file-nr
# 第一列已分配,第二列已使用未释放,第三列最大

十二、回滚方案

12.1 sysctl 回滚

   bash# 从备份恢复
cp -a /etc/sysctl.conf.bak /etc/sysctl.conf
sysctl -p

# 验证
sysctl net.core.somaxconn

12.2 limits.conf 回滚

   bash# 从备份恢复
cp -a /etc/security/limits.conf.bak /etc/security/limits.conf

# 当前会话生效需要重新登录
# 新进程会立即生效

12.3 杀进程回滚(重启进程)

   bash# 如果杀错了进程,立即重启
systemctl restart <service>
# 或
/usr/bin/<service> --config /etc/<service>.conf &

# 验证
systemctl status <service>
ss -tlnp | grep <port>

12.4 配置文件回滚

   bash# sshd
cp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
systemctl reload sshd

# nginx
cp -a /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf
nginx -t && nginx -s reload

# mysql
cp -a /etc/my.cnf.bak /etc/my.cnf
systemctl restart mysqld

12.5 应用配置回滚

   bash# 1. 从备份恢复代码
git checkout HEAD~1

# 2. 重启应用
systemctl restart myapp

# 3. 验证业务
curl http://localhost:8080/health

12.6 流量切回

   bash# 如果切流后业务还是慢,切回旧版本
# 走 CDN/GSLB 控制台切回

# 如果是 K8s,调整流量比例
kubectl patch svc myapp -p '{"spec":{"selector":{"version":"v1"}}}'

# 如果是负载均衡调整
# 走 SLB 控制台

12.7 回滚原则

  • 所有配置修改前必须备份;
  • 所有修复操作必须可回滚;
  • 回滚后必须验证业务;
  • 回滚操作要写入 incident 报告;
  • 回滚和修复要走变更流程。

十三、生产环境注意事项

13.1 变更窗口

  • 紧急修复可立即执行(视为紧急变更);
  • 大型修复(内核参数调整、数据库参数)必须低峰期;
  • 涉及多主机的批量修复必须分批灰度;
  • 涉及架构变更(迁移、扩容)必须先评估;
  • 变更前通知所有相关方;
  • 变更期间监控告警灵敏度提高;
  • 变更后观察 24h-72h。

13.2 监控告警

  • 必须有 CPU、内存、磁盘、网络的基础监控;
  • 必须有应用层的监控(QPS、延迟、错误率);
  • 必须有日志监控(关键字告警);
  • 必须有 JVM/数据库等运行时监控;
  • 告警阈值要结合业务基线;
  • 告警要有分级(warning、critical);
  • 告警要有抑制规则,避免告警风暴。

13.3 容量规划

  • 基于历史数据预测未来容量;
  • 定期压测验证容量上限;
  • 业务上线前评估容量影响;
  • 定期清理历史数据;
  • 扩容要有预案(横向、纵向);
  • 缩容要小心,可能影响可用性。

13.4 应急响应

  • 应急流程要写入 Runbook;
  • 应急联系人要轮值;
  • 应急演练要定期进行;
  • 应急工具要提前准备好(脚本、文档);
  • 应急操作要可回滚;
  • 应急后必须复盘。

13.5 团队协作

  • 排查要避免单兵作战;
  • 关键操作必须双人复核;
  • 排查结果要共享;
  • 复盘要公开;
  • 改进项要跟踪闭环。

13.6 工具与平台

  • Prometheus + Grafana:监控可视化;
  • node_exporter:基础指标采集;
  • process-exporter:进程指标;
  • nvidia_gpu_exporter:GPU 指标(如果有);
  • ELK/EFK:日志聚合;
  • Alertmanager:告警聚合;
  • 堡垒机:操作审计;
  • Ansible:批量运维;
  • 蓝绿部署/灰度发布:降低发布风险。

十四、总结

“系统变慢”是运维最常见的问题之一,也是最能体现基本功的问题。把这 8 个命令用熟,能解决 80% 的问题:

  1. uptime / top:一眼看负载;
  2. vmstat 1 5:CPU + 内存 + IO 概览;
  3. iostat -xz 1:磁盘 IO 详情;
  4. free -h:内存详情;
  5. df -h + du:磁盘空间;
  6. ss -antp:网络连接;
  7. pidstat / strace / perf:进程维度;
  8. dmesg -T + journalctl:内核与系统日志。

把这 8 个命令沉淀成肌肉记忆,配合”系统全局 → 维度深入 → 进程定位 → 根因分析 → 应急处置 → 验证”的固定流程,首次定位时间从 30 分钟降到 5 分钟是完全可能的。

最后强调几个易踩的坑:

  1. 不要只看 top,不看 iostat —— IO 瓶颈容易被忽视;
  2. 不要只看 load,不看 iowait —— IO 满时 CPU 空闲但 load 高;
  3. 不要只看 free,不看 available —— buffer/cache 可回收;
  4. 不要只看 %util,不看 await —— SSD 上 %util 不可信;
  5. 不要只杀进程,不查根因 —— 治标不治本;
  6. 不要直接 rm 正在写的日志 —— 用 truncate
  7. 不要在排查时改内核参数 —— 先观察,再优化;
  8. 不要单凭一条线索下结论 —— 多维度证据关联。

把”排查路径速查表”打印贴到工位,把”应急 Runbook”沉淀到知识库,把”监控告警”部署到所有节点,把”应急演练”排进月度计划。这四件事做完,团队处理”系统变慢”的能力会上一个台阶。

真正的运维能力不是会多少花哨的工具,而是能在压力下用最短时间找到根因。能找到根因,问题就解决了一半。

Linux 系统变慢?用这 8 个命令快速定位瓶颈插图

本文链接:https://www.yunweipai.com/49319.html

下一篇:

网友评论comments

发表回复

您的电子邮箱地址不会被公开。

暂无评论

Copyright © 2012-2022 YUNWEIPAI.COM - 运维派 京ICP备16064699号-6
扫二维码
扫二维码
返回顶部