Linux 系统变慢?用这 8 个命令快速定位瓶颈
一、问题背景
"系统变慢了"是运维群里出现频率最高的一句话。来源可能是用户、业务方、监控告警、值班人员。症状也很杂:网页打开慢、SSH 上去操作卡、SQL 查询慢、视频卡顿、定时任务跑不完、K8s Pod 频繁 OOM。
但"慢"本身不是结论,是一个症状。要解决它,必须先知道"慢在哪里"。常见瓶颈分布在四层:
- CPU 层:进程占用过高、上下文切换过载、软中断打满、单线程跑满核;
- 内存层:可用内存耗尽、swap 飙升、OOM 杀进程、page cache 抖动;
- IO 层:磁盘 await 飙升、IO 队列堆积、inode 耗尽、fd 耗尽、日志写爆盘;
- 网络层:带宽打满、丢包、重传、连接数耗尽、DNS 解析慢、TIME_WAIT 堆积。
每一层的检查工具、关键指标、典型场景都不一样。但大多数运维同学遇到"系统慢"时,第一反应往往就是登录服务器看 top。top 看了半天也没找到问题根源,时间一两个小时过去了,业务受损还在持续。
这篇文章把"系统慢"的标准排查路径沉淀成一套固定的命令组合。8 个核心命令 + 8 个进阶命令 + 完整的排查流程 + 真实场景示例,对照着做,目标是把首次定位时间从 30 分钟压缩到 5 分钟。
写作思路:
- 每个命令给出:目的、用法、预期输出、异常信号、下一步动作;
二、适用场景
本文适用:
- 用户反馈"系统变慢",但没有给出具体症状,需要快速定位瓶颈;
- 监控告警:load average 高、CPU 使用率高、内存使用率高、磁盘使用率高、网络流量异常;
- 应用日志出现超时(read timeout、connection timeout、request timeout);
- 业务请求 P99 / P95 突增,怀疑系统层问题;
- SSH 登录后操作卡顿(命令返回慢、history 加载慢);
- 定时任务跑不完(cron / systemd timer);
- K8s Pod 频繁 OOM Killed、Pending、NotReady;
- 数据库(MySQL/Redis/PG)慢查询,但怀疑不是数据库本身问题;
- Web 服务器(Nginx/Apache)出现 502/504,怀疑系统层问题;
不适用:
- 应用代码 bug(死循环、内存泄漏)——本文聚焦 OS 层;
- 网络层(L4 防火墙、交换机、运营商)问题——需要走网络排障流程;
- 硬件故障(磁盘坏道、内存故障)——需要走硬件更换流程。
三、核心知识点
3.1 性能分析的方法论
USE 方法(Brendan Gregg):
- Utilization(利用率)
- Saturation(饱和度)
- Errors(错误)
应用到这个场景:
- CPU:利用率、运行队列长度、上下文切换、软中断;
- 内存:利用率、可用内存、swap、page fault;
RED 方法:
应用到这个场景:
3.2 load average 的含义
load average 是衡量 Linux 系统负载的核心指标,定义是单位时间内处于可运行状态和不可中断睡眠状态的平均进程数。
- 不可中断睡眠(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):
判断逻辑:
ussy 高:内核态繁忙,可能系统调用过多(高频 write、mmap、epoll);wasihist
3.4 内存维度
free -h 输出:
total used free shared buff/cache availableMem: 15Gi 8.2Gi 1.2Gi 0.0Ki 6.0Gi 6.5GiSwap: 4.0Gi 1.5Gi 2.5Gi
关键指标:
totalusedfreebuff/cache:buffer + page cache(可回收);availableSwap
判断逻辑:
availableswapbuff/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 %utilsda 10 50 500 2000 30 5 35 95
r/srkB/sawaitr_await%util
机械盘 vs SSD:
- 机械盘:IOPS < 200,await 期望 < 10ms,%util 长期 > 80% 说明饱和;
- SSD:IOPS 上万,await 期望 < 1ms,%util 不是判断标准,要看 await。
3.6 网络维度
关键指标:
- 带宽利用率:
sar -n DEV 1、iftop、nethogs; - 丢包率:
netstat -s 中的 segments retransmitted; - 连接数:
ss -s、ss -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 文件系统维度
- fd 耗尽:
cat /proc/sys/fs/file-nr; - 文件系统只读:
dmesg 中 Read-only filesystem; - LVM / mount 问题:
mount、df -h。
3.8 进程维度
ps、pidstat、top 看进程状态:
D 状态进程长时间存在是危险信号(可能是 IO hang 或内核 bug)。
3.9 内核参数
/etc/sysctl.conf 中的关键参数:
vm.swappiness:swap 倾向,0-100,默认 60,云主机常用 10;net.core.somaxconnnet.ipv4.tcp_max_syn_backlognet.ipv4.tcp_tw_reusenet.ipv4.tcp_fin_timeoutnet.core.rmem_default/wmem_defaultfs.file-maxfs.nr_open
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 / 内存 / 磁盘 / 网络哪一层。
uptime# load averagetop -bn1 | head -20 # CPU、内存、进程free -h # 内存df -h # 磁盘ss -s # 网络连接总数dmesg -T | tail -30 # 内核报错
第二层:单维度深入(1-3 分钟)
针对第一层发现的瓶颈,进入对应维度深挖:
- CPU 高 →
mpstat -P ALL 1 5、pidstat -u 1 5、top -c; - 内存高 →
vmstat 1 5、sar -r 1、cat /proc/meminfo; - IO 高 →
iostat -xz 1 5、iotop、pidstat -d 1 5; - 网络高 →
sar -n DEV 1、iftop、nethogs、ss -antp。
第三层:进程维度定位(3-5 分钟)
找到可疑进程后,深入分析:
pidstat -p PID -u -r -d 1 5cat /proc/PID/statuscat /proc/PID/limitsls -l /proc/PID/fd | wc -lpmap -x PIDperf top -p PIDstrace -p PIDlsof -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 -rIO 高 → 哪个设备? ├── %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 个命令快速判断瓶颈层。
# 1. load average 与运行时长uptime# 输出:14:30:01 up 100 days, 23:15, 1 user, load average: 4.50, 5.20, 4.80# 2. CPU、内存、进程 TOPtop -bn1 | head -20# 3. 内存详情free -h# 4. 磁盘使用df -hdf -i# 5. 网络连接统计ss -s# 6. 内核报错dmesg -T | tail -30
预期输出:
- load 接近或超过 CPU 核数:CPU 瓶颈;
freedmesg 出现 OOM、IO error、segfault:内核级问题。
异常表现:
- load 高但 CPU idle 高 → IO wait 高(磁盘/网络瓶颈);
- 内存 available 0 + swap 高 → 内存瓶颈;
dfdmesg 有 TCP: out of memory → 端口/socket 耗尽。
下一步动作:
5.2 步骤二:CPU 维度深入
# 1. 每个 CPU 核心的状态mpstat -P ALL 1 5# 2. 进程级 CPUpidstat -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 5cat /proc/interrupts | head -20# 7. 软中断cat /proc/softirqsmpstat -I ALL 1 5# 8. 运行队列与负载sar -q 1 5# 9. CPU 频率cat /proc/cpuinfo | grep "cpu MHz"lscpu# 10. 单进程系统调用strace -p <PID> -c -fstrace -p <PID> -e trace=network,write,read
预期输出:
mpstat 显示每个核的 usr/sys/iowait/idle;pidstat 显示每个进程的 %user、%system、%guest、%wait;vmstat 输出 procs r b 表示运行中和不可中断进程数。
判断逻辑:
procs rprocs bsystem cs(context switch) > 100k/s:上下文切换过高;system in(interrupt) > 10k/s:中断过高。
异常表现:
下一步动作:
5.3 步骤三:内存维度深入
# 1. 内存详情free -hcat /proc/meminfo# 2. 内存历史vmstat 1 5sar -r 1 5# 3. swap 活动vmstat 1 5sar -S 1 5# 4. OOM 历史dmesg -T | grep -i "out of memory"grep -i "oom" /var/log/messagesjournalctl -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 缓存slabtopcat /proc/slabinfo# 10. page cache 与 buffercat /proc/meminfo | grep -E "Buffers|Cached|SwapTotal|SwapFree"# 11. cgroup 限制cat /sys/fs/cgroup/memory/memory.limit_in_bytescat /sys/fs/cgroup/memory/memory.usage_in_bytescat /sys/fs/cgroup/memory/memory.failcnt
预期输出:
free -h:total/used/free/shared/buff/cache/available;vmstatpmapcgroup
判断逻辑:
availablesi/soOOMcacheslab 占用大:内核对象多(如 dentry、inode);- cgroup
failcnt > 0:触发过 cgroup 限制。
异常表现:
- 单进程 RSS >
total/2:单进程内存占用过大; dentrynfs_*
下一步动作:
- swap 高 → 找占用内存最多的进程或调
vm.swappiness;
5.4 步骤四:磁盘 IO 维度深入
# 1. 系统级 IOvmstat 1 5# 看 bi/bo(block in/out)# 2. 每个磁盘的 IOiostat -xz 1 5iostat -xz -m 1 5# 3. 按进程统计 IOiotop -o -P -d 5# 4. 进程级 IOpidstat -d 1 5# 5. 读写的文件lsof -p <PID> | grep -E "REG|DIR"# 6. 大文件查找find / -size +100M -type f 2>/dev/null | head -20find / -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_requestscat /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;iotoppidstat -d
判断逻辑:
%utilawaitr/s + w/srkB/s + wkB/siostat
异常表现:
- 机械盘
%util 长期 > 80%:磁盘 IO 饱和; - SSD
await > 10ms:SSD 性能问题; find /
下一步动作:
- 调整 IO 调度器(deadline、noop、cfq);
5.5 步骤五:网络维度深入
# 1. 网卡流量sar -n DEV 1 5iftop -i eth0# 2. 按进程统计流量nethogs -d 5# 3. TCP/UDP 连接统计ss -sss -ant | awk '{print $1}' | sort | uniq -c# 4. TIME_WAIT / CLOSE_WAITss -ant state time-wait | wc -lss -ant state close-wait | wc -lss -ant state established | wc -l# 5. 按进程统计 ESTABLISHEDss -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 -sss -s# 7. 丢包与重传netstat -s | grep -E "retransmit|drop|timeout"cat /proc/net/softnet_stat# 8. 网卡中断cat /proc/interrupts | grep eth0watch -n 1 "cat /proc/interrupts | grep eth0"# 9. 抓包tcpdump -i eth0 -nn -s0 -w capture.pcaptcpdump -i eth0 -nn port 80# 10. DNS 解析时间dig +stats example.com# 11. traceroute / mtrmtr -rwc 30 example.com# 12. 内核网络参数sysctl -a | grep -E "net\.(core|ipv4)"
预期输出:
sar -n DEViftopss -ssoftnet_stat
判断逻辑:
- 带宽满:网卡
rxkB/s + txkB/s 接近网卡最大带宽; - 丢包:
/proc/net/softnet_stat 第二列很大; retransmit- DNS 慢:resolver 配置或上游 DNS 问题。
异常表现:
- CLOSE_WAIT 持续上涨:业务没正常关闭连接;
- TIME_WAIT 涨到几十万:短连接服务需要内核参数优化;
下一步动作:
- TIME_WAIT 多 → 调整内核参数(
tcp_tw_reuse、tcp_tw_recycle);
5.6 步骤六:进程维度深挖
# 1. 进程状态ps -eo pid,user,stat,etime,pcpu,pmem,args | head -20# 2. 进程 /proc/<PID>/ 详细信息PID=12345cat /proc/$PID/statuscat /proc/$PID/statcat /proc/$PID/cmdlinels -la /proc/$PID/exels -la /proc/$PID/cwdls -la /proc/$PID/fd | wc -lcat /proc/$PID/limitscat /proc/$PID/smaps_rollup# 3. 进程打开的文件lsof -p $PID | head -30lsof -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 $PIDperf record -p $PID -g -- sleep 10perf report# 8. 系统调用热点strace -p $PID -cstrace -p $PID -e trace=network,read,write -c# 9. 进程关联的内核调用cat /proc/$PID/wchancat /proc/$PID/syscall# 10. 子进程ps --ppid $PID# 11. 线程ps -eLf | grep $PID | headcat /proc/$PID/status | grep Threads# 12. 进程优先级chrt -p $PIDcat /proc/$PID/stat | awk '{print "priority="$18,"nice="$19}'
预期输出:
/proc/PID/status:State、VmRSS、Threads、voluntary_ctxt_switches 等;lsofperf topstrace -c
判断逻辑:
- 进程 State 为 D:IO 等待,需要看
wchan; ThreadsfdVmRSSvoluntary_ctxt_switchesnonvoluntary_ctxt_switches
异常表现:
- perf top 显示某函数占用高:CPU 热点定位;
- strace 显示某 syscall 频繁:系统调用热点。
下一步动作:
- CPU 热点:perf + FlameGraph 分析;
- syscall 热点:调小 syscall 频率或换更高效的调用。
5.7 步骤七:常见瓶颈场景排查示例
场景 1:CPU 跑满
# 现象uptime# load average: 24.50, 25.20, 24.80# 4 核 CPUtop -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
# 现象free -h# available 0# swap used 4Gdmesg -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 满
# 现象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:磁盘写满
# 现象df -h# /var 100%业务报错:No space left on device# 定位du -sh /var/* | sort -h | tail# /var/log/messages 占 200G# 进一步分析ls -la /var/log/messages# 文件 200Glsof | 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:网络连接耗尽
# 现象业务报错:Cannot assign requested addressss -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.confsysctl -p# 2. 开启 TIME_WAIT 复用echo"net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.confsysctl -p
场景 6:fd 耗尽
# 现象业务报错:Too many open filescat /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. 调大 ulimitecho"ulimit -n 65535" >> /etc/security/limits.conf# 2. 排查 fd 泄漏(用 lsof 看哪些 fd 不该开)
5.8 步骤八:应急处置
# 1. 杀进程(先 STOP 留证据,再 TERM,最后 KILL)kill -STOP <PID> # 暂停进程,便于排查kill -CONT <PID> # 恢复进程kill -TERM <PID> # 优雅退出sleep 5kill -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.sliceecho <PID> > /sys/fs/cgroup/cpu/test.slice/tasksecho 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 ACCEPTiptables -I OUTPUT -p tcp --dport 80 -j DROP# 5. 卸载磁盘(紧急)umount /data # 会影响正在使用该盘的业务# 6. 紧急扩容(云环境)# 走云厂商 API# 7. 切流(CDN/GSLB)# 走运维平台切流# 8. 重启服务systemctl restart <service>
5.9 步骤九:长期治理
# 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.comab -n 100000 -c 1000 http://example.com/# 4. 优化(应用/配置/架构)# 应用:缓存、异步、批量# 配置:内核参数、连接池# 架构:读写分离、分库分表、CDN、缓存层# 5. Runbook# 把排查路径沉淀到 Runbook# 把常见问题写成 FAQ# 把应急流程做成 Ansible role
六、常用命令
6.1 综合快查
uptimetop -bn1 | head -20free -hdf -hdf -iss -sdmesg -T | tail -30
6.2 CPU
tophtopmpstat -P ALL 1 5mpstat -I ALL 1 5pidstat -u 1 5vmstat 1 5sar -u 1 5perf topperf record -g -p <PID> -- sleep 10 && perf reportstrace -p <PID>cat /proc/loadavgcat /proc/cpuinfolscpu
6.3 内存
free -hcat /proc/meminfovmstat 1 5sar -r 1 5sar -S 1 5slabtopdmesg | grep -i oomps -eo pid,user,rss,args --sort=-rss | headpmap -x <PID>cat /proc/<PID>/smaps_rollupcat /proc/<PID>/status
6.4 IO
iostat -xz 1 5iostat -xz -m 1 5iotop -o -Ppidstat -d 1 5vmstat 1 5 # bi/bosar -d 1 5lsof -p <PID> | grep REGfind / -size +1G -type f 2>/dev/nulldu -sh /var/log/* | sort -hlsof | grep deleted
6.5 网络
sar -n DEV 1 5sar -n EDEV 1 5iftop -i eth0nethogs -d 5ss -sss -ant | awk '{print $1}' | sort | uniq -css -antp state establishednetstat -scat /proc/net/softnet_stattcpdump -i eth0 -nn -s0 -w capture.pcapmtr -rwc 30 example.comdig +stats example.com
6.6 进程
ps auxfps -eo pid,ppid,user,pcpu,pmem,args --sort=-pcpu | headtop -Hp <PID>pidstat -p <PID> -u -r -d 1 5cat /proc/<PID>/statuscat /proc/<PID>/cmdlinels -la /proc/<PID>/exels -la /proc/<PID>/fd | wc -llsof -p <PID>pstree -ap <PID>
6.7 内核
sysctl -asysctl -pcat /etc/sysctl.confuname -admesg -Tjournalctl -k
6.8 应急
kill -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 DROPumount /dataswapoff /dev/sda2
七、配置示例
7.1 sysctl 内核参数调优(/etc/sysctl.conf)
# ---------- 内存 ----------vm.swappiness = 10vm.dirty_ratio = 15vm.dirty_background_ratio = 5vm.vfs_cache_pressure = 100# ---------- 网络 ----------net.core.somaxconn = 65535net.core.rmem_default = 262144net.core.wmem_default = 262144net.core.rmem_max = 16777216net.core.wmem_max = 16777216net.core.netdev_max_backlog = 65535net.ipv4.tcp_max_syn_backlog = 65535net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 0 # 注意:4.12+ 已废弃net.ipv4.tcp_fin_timeout = 15net.ipv4.tcp_keepalive_time = 600net.ipv4.tcp_keepalive_intvl = 30net.ipv4.tcp_keepalive_probes = 3net.ipv4.tcp_slow_start_after_idle = 0net.ipv4.ip_local_port_range = 1024 65535# ---------- 文件系统 ----------fs.file-max = 2097152fs.nr_open = 1048576fs.inotify.max_user_watches = 524288fs.inotify.max_user_instances = 8192# ---------- 内核 ----------kernel.pid_max = 4194304kernel.threads-max = 4194304kernel.shmmax = 68719476736kernel.shmall = 4294967296# ---------- 容器/cgroup 相关 ----------net.ipv4.ip_forward = 1net.bridge.bridge-nf-call-iptables = 1net.bridge.bridge-nf-call-ip6tables = 1
加载:
7.2 limits.conf(/etc/security/limits.conf)
# 系统全局* soft nofile 65535* hard nofile 65535* soft nproc 65535* hard nproc 65535# 特定用户mysql soft nofile 65535mysql hard nofile 65535mysql soft nproc 65535mysql hard nproc 65535# rootroot soft nofile 1048576root hard nofile 1048576
7.3 Prometheus node_exporter 告警规则
groups:-name:node_alertsrules:-alert:HighLoadAverageexpr:node_load5>(countby(instance)(node_cpu_seconds_total{mode="idle"})*1.5)for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} 5 分钟 load 高于 CPU 核数 1.5 倍"-alert:HighCPUUsageexpr:(1-avgby(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])))*100>80for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} CPU 使用率超过 80%"-alert:HighMemoryUsageexpr:(1-(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes))*100>85for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} 内存使用率超过 85%"-alert:HighDiskUsageexpr:(1-(node_filesystem_avail_bytes{fstype!="tmpfs"}/node_filesystem_size_bytes{fstype!="tmpfs"}))*100>85for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }}{{ $labels.mountpoint }} 磁盘使用率超过 85%"-alert:HighDiskIOexpr:rate(node_disk_io_time_seconds_total[5m])*100>80for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} 磁盘 {{ $labels.device }} IO 使用率超过 80%"-alert:DiskAwaitHighexpr:rate(node_disk_read_time_seconds_total[5m])/rate(node_disk_reads_completed_total[5m])>0.05for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} 磁盘 {{ $labels.device }} await 超过 50ms"-alert:HighNetworkTrafficexpr:rate(node_network_receive_bytes_total{device!="lo"}[5m])*8>8000000000for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} 网络接收速率超过 8Gbps"-alert:HighConntrackUsageexpr:node_nf_conntrack_entries/node_nf_conntrack_entries_limit*100>80for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} conntrack 表使用率超过 80%"-alert:OOMKilledexpr:increase(node_vmstat_oom_kill[5m])>0for:0mlabels:severity:criticalannotations:summary:"{{ $labels.instance }} 发生 OOM"-alert:HighContextSwitchexpr:rate(node_context_switches_total[5m])>100000for:5mlabels:severity:warningannotations:summary:"{{ $labels.instance }} 上下文切换超过 10万/s"
7.4 自动化巡检脚本(/usr/local/bin/sys_health_check.sh)
#!/usr/bin/env bash# 系统健康巡检# 输出:/var/log/sys_health/$(hostname)-$(date +%F).logLOG_DIR=/var/log/sys_healthLOG_FILE="$LOG_DIR/$(hostname)-$(date +%F).log"mkdir -p "$LOG_DIR"exec > >(tee -a "$LOG_FILE") 2>&1echo"===== System Health Check ====="echo"Time: $(date '+%F %T')"echo"Hostname: $(hostname)"echo"----- Uptime -----"uptimeecho"----- CPU -----"top -bn1 | head -10echo"----- Memory -----"free -hecho"Swap info:"cat /proc/meminfo | grep -E "SwapTotal|SwapFree"echo"----- Disk -----"df -hdf -iecho"----- Disk IO -----"iostat -xz 1 3 2>/dev/null || echo"iostat not installed"echo"----- Network -----"ss -secho"Established connections:"ss -antp state established | head -20echo"----- Top 10 CPU -----"ps -eo pid,ppid,user,pcpu,pmem,etime,args --sort=-pcpu | head -10echo"----- Top 10 Memory -----"ps -eo pid,ppid,user,pcpu,pmem,rss,args --sort=-rss | head -10echo"----- 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 -5echo"----- Load Average -----"cat /proc/loadavgecho"----- Conntrack -----"cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/nullcat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/nullecho"----- File Descriptor -----"cat /proc/sys/fs/file-nrecho"===== End ====="
chmod +x /usr/local/bin/sys_health_check.sh# 每天跑一次cat > /etc/cron.d/sys_health <<'EOF'0 8 * * * root /usr/local/bin/sys_health_check.shEOF
7.5 Grafana 面板 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 关键指标速查
| | | | |
|---|
| | uptime | | |
| | top | | |
| | top | | |
| | vmstat | | |
| | vmstat | | |
| | free | | |
| | free | | |
| | dmesg | | |
| | iostat | | |
| | iostat | | |
| | df | | |
| | df -i | | |
| | sar -n DEV | | |
| | ss | | |
| | ss | | |
| | netstat -s | | |
| | /proc/PID/fd | | |
| | ps | | |
| | ps | | |
8.2 重点日志
| |
|---|
/var/log/messages | |
/var/log/syslog | |
/var/log/kern.log | |
/var/log/dmesg | |
/var/log/cron | |
| |
| 在 /var/log/<app>/ 或 /data/logs/ |
8.3 关键观察方法
vmstat 1 5iostat -xz 1 5sar -u -r -d -n DEV 1 100perf record/reportstrace -p PID -ctcpdump -wjournalctl -kausearch
九、排查路径
9.1 排查路径速查表
| | | |
|---|
| | uptime | |
| | top -c | |
| | top -Hp PID | |
| | ps -eo --sort=-rss | |
| | | |
| | du -sh | |
| | iotop | |
| | | |
| | lsof -p | |
| | sar -n DEV | |
| | netstat -s | |
| | dig +stats | |
| | | |
| | ss -antp | |
| | uptime | |
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 -STOPkill -TERMkill -9 跳过清理逻辑,可能导致共享内存泄漏、socket 没关闭;kill -9kill -9 -1 会杀所有进程,等于 pkill -9 -P 1,慎用。
10.2 修改内核参数风险
sysctl -pvm.swappiness 调到 0:内核只在紧急情况下 swap,可能 OOM;vm.swappinesstcp_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- 不要在 logrotate 配置错误时手动清理,会导致日志断层。
10.5 重启服务风险
10.6 批量脚本风险
- 不要在生产环境无审阅执行
ansible all -m shell -a 'rm -rf /tmp/*'。
10.7 数据迁移风险
10.8 误判风险
- 单核 100% 不一定是瓶颈,可能是单线程程序的正常行为;
- load 高不一定是系统问题,可能是业务正常增长;
- 内存占用高不一定是泄漏,可能是 Linux 的 page cache;
十一、验证方式
11.1 验证 CPU
# 1. 实时看 CPUtophtopmpstat -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 验证内存
# 1. 看 availablefree -h# available 应该 > total * 20%# 2. 看 swap 活动vmstat 1 5# si/so 应该接近 0# 3. 看 OOM 是否停止dmesg -T | grep -i oom# 应该没有新 OOM# 4. 看进程 RSSps -eo pid,rss,args --sort=-rss | head# 内存占用应该稳定或下降
11.3 验证磁盘
# 1. 看磁盘使用率df -h# 应该 < 80%# 2. 看磁盘 IOiostat -xz 1 5# %util 应该 < 70%,await 应该正常# 3. 看 inodedf -i# 应该 < 80%# 4. 看是否有 deleted 文件lsof | grep deleted# 应该没有大文件
11.4 验证网络
# 1. 看带宽sar -n DEV 1 5# rxkB/s + txkB/s 应该 < 带宽 * 70%# 2. 看连接数ss -s# 各状态连接数应该稳定# 3. 看 TIME_WAITss -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 验证业务
# 1. 应用日志tail -f /var/log/app/app.log# 应该没有 timeout、error# 2. 监控告警# 应该没有 critical 告警# 3. 用户反馈# 通过客服、工单、用户群确认恢复# 4. 关键指标# P99 延迟、错误率、QPS 回归基线
11.6 验证内核参数
# 看参数是否生效sysctl net.core.somaxconnsysctl vm.swappiness# 看进程 ulimitcat /proc/<PID>/limits | grep "open files"# 看文件描述符cat /proc/sys/fs/file-nr# 第一列已分配,第二列已使用未释放,第三列最大
十二、回滚方案
12.1 sysctl 回滚
# 从备份恢复cp -a /etc/sysctl.conf.bak /etc/sysctl.confsysctl -p# 验证sysctl net.core.somaxconn
12.2 limits.conf 回滚
# 从备份恢复cp -a /etc/security/limits.conf.bak /etc/security/limits.conf# 当前会话生效需要重新登录# 新进程会立即生效
12.3 杀进程回滚(重启进程)
# 如果杀错了进程,立即重启systemctl restart <service># 或/usr/bin/<service> --config /etc/<service>.conf &# 验证systemctl status <service>ss -tlnp | grep <port>
12.4 配置文件回滚
# sshdcp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_configsystemctl reload sshd# nginxcp -a /etc/nginx/nginx.conf.bak /etc/nginx/nginx.confnginx -t && nginx -s reload# mysqlcp -a /etc/my.cnf.bak /etc/my.cnfsystemctl restart mysqld
12.5 应用配置回滚
# 1. 从备份恢复代码git checkout HEAD~1# 2. 重启应用systemctl restart myapp# 3. 验证业务curl http://localhost:8080/health
12.6 流量切回
# 如果切流后业务还是慢,切回旧版本# 走 CDN/GSLB 控制台切回# 如果是 K8s,调整流量比例kubectl patch svc myapp -p '{"spec":{"selector":{"version":"v1"}}}'# 如果是负载均衡调整# 走 SLB 控制台
12.7 回滚原则
十三、生产环境注意事项
13.1 变更窗口
13.2 监控告警
- 告警要有分级(warning、critical);
13.3 容量规划
13.4 应急响应
13.5 团队协作
13.6 工具与平台
- Prometheus + Grafana:监控可视化;
- nvidia_gpu_exporter:GPU 指标(如果有);
十四、总结
"系统变慢"是运维最常见的问题之一,也是最能体现基本功的问题。把这 8 个命令用熟,能解决 80% 的问题:
uptimevmstat 1 5iostat -xz 1free -hdf -hss -antppidstatdmesg -T
把这 8 个命令沉淀成肌肉记忆,配合"系统全局 → 维度深入 → 进程定位 → 根因分析 → 应急处置 → 验证"的固定流程,首次定位时间从 30 分钟降到 5 分钟是完全可能的。
最后强调几个易踩的坑:
- 不要只看
top,不看 iostat —— IO 瓶颈容易被忽视; - 不要只看 load,不看
iowait —— IO 满时 CPU 空闲但 load 高; - 不要只看
free,不看 available —— buffer/cache 可回收; - 不要只看
%util,不看 await —— SSD 上 %util 不可信; - 不要直接
rm 正在写的日志 —— 用 truncate;
把"排查路径速查表"打印贴到工位,把"应急 Runbook"沉淀到知识库,把"监控告警"部署到所有节点,把"应急演练"排进月度计划。这四件事做完,团队处理"系统变慢"的能力会上一个台阶。
真正的运维能力不是会多少花哨的工具,而是能在压力下用最短时间找到根因。能找到根因,问题就解决了一半。