




















https://mp.weixin.qq.com/s/YC880xAiCdsRbbdpaRWXMA?mpshare=1&scene=1&srcid=1102k8a0975YxpKRNMJgC2he&sharer_shareinfo=9ea5ee22f4579d0017aeb6a295d5b7a4&sharer_shareinfo_first=9ea5ee22f4579d0017aeb6a295d5b7a4&color_scheme=light#rd
vmstat是快速了解系统整体状况的首选工具,它能实时展示进程、内存、交换、I/O和CPU等关键指标。
基础用法:
# 每2秒采样一次,共采样5次
vmstat 2 5
输出示例与解读:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 524288 102400 2048576 0 0 10 50 200 400 25 5 68 2 0
1 0 0 520192 102400 2052672 0 0 0 100 180 380 20 4 76 0 0
关键指标解析:
实战案例 - 内存泄漏检测:
# 监控30分钟,每分钟采样
vmstat 60 30 > vmstat_log.txt
# 分析内存使用趋势
awk '{if(NR>2) print $4}' vmstat_log.txt | \
gnuplot -e "set terminal dumb; plot '-' with lines"
如果free列持续下降,cache和buff不变,可能存在内存泄漏。
iostat提供详细的CPU和磁盘I/O统计,是诊断磁盘瓶颈的利器。
实用命令:
# 显示扩展统计,每3秒更新
iostat -x 3
# 只显示磁盘统计
iostat -d 2
# 按MB显示,更直观
iostat -m 3
输出详解:
Device r/s w/s rMB/s wMB/s await util
sda 50.2 120.5 2.3 15.8 18.5 85.2
sdb 5.1 2.3 0.5 0.3 2.1 12.5
关键指标:
实战案例 - 数据库慢查询诊断:
# 持续监控,记录I/O峰值
iostat -x 1 60 | tee iostat_db.log
# 同时抓取数据库慢查询日志时间戳
# 对比时间点,定位是否I/O导致查询变慢
某电商系统案例:发现订单查询缓慢,通过iostat发现await达到150ms,util持续95%。进一步分析发现订单表未建索引,全表扫描导致大量随机I/O。添加索引后,await降至5ms,查询速度提升30倍。
dstat整合了多个工具的功能,用彩色输出展示系统全貌。
推荐用法:
# 综合显示CPU、磁盘、网络、内存
dstat -cdnm 2
# 显示最耗资源的进程
dstat -c --top-cpu --top-mem 3
# 监控特定磁盘和网络接口
dstat -d -D sda,sdb -n -N eth0 2
输出示例:
----total-cpu-usage---- -dsk/total- -net/total- ------memory-usage-----
usr sys idl wai hiq siq| read writ| recv send| used buff cach free
25 5 68 2 0 0| 50k 200k| 0 1.2M| 3.8G 100M 2.0G 500M
30 8 60 2 0 0| 100k 500k| 500k 2.5M| 3.9G 100M 2.0G 450M
实战场景 - 多维度性能关联分析:
某视频转码服务器出现卡顿,使用dstat同时监控发现:
usr达到95%,转码进程占用高问题定位:转码、写盘、网络传输同时进行,资源竞争严重。优化方案:转码完成后再传输,错峰处理,性能提升40%。
top高级用法:
# 启动top后的交互命令
# 按P - 按CPU排序
# 按M - 按内存排序
# 按c - 显示完整命令
# k - 杀死进程
# 1 - 显示每个CPU核心
# f - 选择显示字段
# 批处理模式,记录前10个进程
top -b -n 1 | head -20
# 监控特定用户的进程
top -u mysql
htop优势特性:
# 安装htop
sudo apt install htop # Debian/Ubuntu
sudo yum install htop # CentOS/RHEL
# 功能特点:
# - 彩色显示,更直观
# - 支持鼠标操作
# - 横向滚动查看完整命令
# - 树状显示进程关系(F5)
# - 可视化CPU/内存/交换区使用
实战案例 - Java应用内存溢出:
# 发现Java进程内存持续增长
htop -p $(pgrep -d',' java)
# 观察到堆内存接近Xmx限制
# 使用jstat进一步分析GC
jstat -gcutil $(pgrep java) 1000
# 发现Full GC频繁,最终OOM
# 导出堆转储分析
jmap -dump:format=b,file=heap.bin $(pgrep java)
pidstat是sysstat包的一部分,能精确追踪进程级别的资源消耗。
核心用法:
# CPU使用统计
pidstat -p ALL 2
# 内存使用统计
pidstat -r 2
# I/O统计
pidstat -d 2
# 线程级别统计
pidstat -t 2
# 监控特定进程
pidstat -p 1234 1
输出解析:
# pidstat -d 2
Time PID kB_rd/s kB_wr/s kB_ccwr/s Command
14:20:31 2345 0.00 512.50 0.00 mysqld
14:20:33 2345 1024.50 2048.75 0.00 mysqld
实战案例 - 定位异常进程:
某生产环境CPU突然飙升至100%,使用排查流程:
# 1. 快速定位高CPU进程
pidstat -u 1 5 | sort -k 7 -r | head
# 输出显示PID 3456的python进程CPU达到98%
# 2. 查看该进程线程情况
pidstat -t -p 3456 1
# 发现单个线程占用全部CPU
# 3. 使用strace追踪系统调用
strace -p 3456 -c
# 发现大量无效的正则匹配调用
# 4. 查看进程代码上下文
ps -p 3456 -o cmd
# 定位到异常正则表达式导致的回溯爆炸
iotop以类似top的界面显示进程I/O使用情况。
使用方法:
# 基础用法
sudo iotop
# 只显示活跃进程
sudo iotop -o
# 累积模式(显示总I/O而非速率)
sudo iotop -a
# 监控特定进程
sudo iotop -p 1234
交互命令:
r - 反向排序o - 切换只显示活跃进程a - 切换累积/当前模式q - 退出实战案例 - 日志服务I/O优化:
某日志收集系统磁盘I/O持续高位:
# 使用iotop定位
sudo iotop -a -o
# 发现logstash进程每秒写入100MB
# 分析日志配置
# 问题:每条日志立即刷盘,未批量处理
# 优化配置,启用批量写入
# 修改后I/O降低80%,吞吐量提升5倍
实用命令集:
# 显示所有TCP连接
netstat -ant
# 显示监听端口
netstat -tunlp
# 显示网络统计
netstat -s
# 显示路由表
netstat -r
# 持续监控连接数变化
watch -n 1 "netstat -an | grep ESTABLISHED | wc -l"
连接状态解读:
实战案例 - TIME_WAIT过多问题:
# 检查TIME_WAIT数量
netstat -an | grep TIME_WAIT | wc -l
# 输出: 28000 (危险水平)
# 查看TIME_WAIT分布
netstat -an | awk '/TIME_WAIT/{print $5}' | \
cut -d: -f1 | sort | uniq -c | sort -rn | head
# 发现大量短连接导致
# 解决方案:
# 1. 调整内核参数
echo"net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo"net.ipv4.tcp_tw_recycle = 1" >> /etc/sysctl.conf
sysctl -p
# 2. 应用层启用连接池
# 连接复用后TIME_WAIT降至2000以下
ss比netstat更快,信息更丰富。
高级用法:
# 显示TCP连接及内存使用
ss -tm
# 显示进程信息
ss -tp
# 过滤特定状态
ss state established
# 显示特定端口连接
ss -tn sport = :80
# 显示连接速率信息
ss -ti
# 统计各状态连接数
ss -tan | awk '{print $1}' | sort | uniq -c
实战案例 - 追踪连接来源:
# 发现服务器连接异常增多
ss -tn | awk '{print $4}' | cut -d: -f1 | \
sort | uniq -c | sort -rn | head
# 输出显示某IP建立了5000+连接
# 确认为DDoS攻击,添加防火墙规则
iptables -A INPUT -s 攻击IP -j DROP
strace能追踪进程的系统调用和信号,是调试程序异常的强大工具。
核心用法:
# 追踪新进程
strace ./myprogram
# 附加到运行中的进程
strace -p 1234
# 统计系统调用
strace -c ./myprogram
# 追踪特定系统调用
strace -e open,read,write ./myprogram
# 追踪文件操作
strace -e trace=file ./myprogram
# 追踪网络操作
strace -e trace=network ./myprogram
# 保存到文件并显示时间戳
strace -tt -o trace.log ./myprogram
# 追踪子进程
strace -f ./myprogram
输出示例:
open("/etc/passwd", O_RDONLY) = 3
read(3, "root:x:0:0:root:/root:/bin/bash\n", 4096) = 1024
close(3) = 0
实战案例 - 程序启动失败调试:
某应用启动后立即退出,无日志输出:
# 使用strace追踪
strace -e trace=file ./app 2>&1 | grep -E "ENOENT|EACCES"
# 输出显示:
open("/opt/app/config.ini", O_RDONLY) = -1 ENOENT (No such file or directory)
# 发现配置文件缺失
# 另一个案例:权限问题
open("/var/log/app.log", O_WRONLY|O_CREAT) = -1 EACCES (Permission denied)
# 修复日志目录权限后程序正常运行
实战案例 - 性能问题分析:
# 程序运行缓慢,统计系统调用耗时
strace -c ./slow_app
# 输出:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.85 4.523891 45238 100 fsync
0.10 0.004512 45 100 write
0.05 0.002256 23 100 open
# 发现fsync调用占用99%时间
# 分析代码,每次写入都强制刷盘
# 优化为批量fsync,性能提升100倍
Linux中"一切皆文件",lsof能列出进程打开的所有文件,包括普通文件、目录、网络socket、设备等。
常用命令:
# 列出所有打开的文件
lsof
# 查看特定进程打开的文件
lsof -p 1234
# 查看特定文件被哪些进程打开
lsof /var/log/syslog
# 查看特定用户打开的文件
lsof -u username
# 查看特定端口
lsof -i :80
# 查看网络连接
lsof -i
# 查看特定协议
lsof -i tcp
lsof -i udp
# 组合查询
lsof -i tcp:80 -t # 只显示PID
# 查看文件描述符泄漏
lsof -p 1234 | wc -l
实战案例 - 磁盘空间异常:
某服务器df显示磁盘已满,但du统计目录占用空间却不多:
# 查找已删除但未释放的文件
lsof | grep deleted
# 输出显示:
app 1234 user 3w REG 8,1 5368709120 deleted /var/log/huge.log
# 进程1234仍持有已删除文件的句柄,占用5GB
# 解决方法:
# 方案1: 重启进程释放句柄
kill -HUP 1234
# 方案2: 截断文件描述符
cat /dev/null > /proc/1234/fd/3
# 磁盘空间立即释放
实战案例 - 端口占用排查:
# 启动服务失败:端口已占用
lsof -i :8080
# 输出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 2345 app 45u IPv6 12345 0t0 TCP *:8080 (LISTEN)
# 发现旧进程未正常关闭
kill 2345
# 或查找所有监听端口
lsof -i -sTCP:LISTEN
参考这篇文章: Linux性能分析:perf火焰图以及性能开销
在多核系统中,mpstat能显示每个CPU核心的使用情况,识别CPU负载不均问题。
使用方法:
# 显示所有CPU统计
mpstat -P ALL 2
# 显示特定CPU
mpstat -P 0,1 2
# 输出示例:
CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
all 25.50 0.00 5.23 2.10 0.00 0.50 0.00 0.00 0.00 66.67
0 85.23 0.00 10.12 1.50 0.00 0.80 0.00 0.00 0.00 2.35
1 5.12 0.00 2.34 0.50 0.00 0.20 0.00 0.00 0.00 91.84
2 10.45 0.00 3.12 5.20 0.00 0.30 0.00 0.00 0.00 80.93
3 8.90 0.00 2.80 1.10 0.00 0.25 0.00 0.00 0.00 86.95
实战案例 - CPU绑定优化:
某多线程应用性能不理想,mpstat显示CPU 0使用率95%,其他核心空闲:
# 确认进程线程CPU亲和性
taskset -cp $(pgrep myapp)
# 输出: pid 1234's current affinity list: 0
# 问题:所有线程绑定到CPU 0
# 解决:取消CPU绑定,让调度器自动分配
taskset -cp 0-3 1234
# 或在代码中设置线程亲和性
# 优化后4个核心均衡负载,吞吐量提升3倍
症状: 用户反馈网站打开慢,响应时间从200ms增加到5秒。
排查流程:
# 第1步:系统整体检查
vmstat 1 10
# 观察:CPU idle 30%,wa(等待I/O)达到40%,初步判断I/O瓶颈
# 第2步:确认I/O瓶颈
iostat -x 2 5
# 发现:sda的util达到98%,await超过200ms,确认磁盘瓶颈
# 第3步:定位进程
iotop -o
# 发现:MySQL进程I/O最高,每秒写入150MB
# 第4步:分析MySQL状态
mysql -e "SHOW FULL PROCESSLIST;"
# 发现大量慢查询
mysql -e "SHOW ENGINE INNODB STATUS\G" | grep "queries inside"
# 显示:120 queries inside InnoDB
# 第5步:查看慢查询日志
tail -f /var/log/mysql/slow.log
# 发现某个订单查询频繁,无索引,全表扫描
# 第6步:添加索引
ALTER TABLE orders ADD INDEX idx_user_date (user_id, create_date);
# 第7步:验证效果
iostat -x 2 5
# util降至20%,await降至8ms
# 监控响应时间
curl -w "@curl-format.txt" -o /dev/null -s http://localhost/
# 响应时间恢复至150ms
根本原因: 订单表缺少索引,大量请求导致全表扫描,磁盘I/O饱和。
解决方案: 添加联合索引,启用查询缓存,优化数据库配置。
效果: 响应时间从5s降至150ms,I/O利用率从98%降至20%。
症状: 应用运行几天后被系统kill,日志显示OOM。
排查流程:
# 第1步:监控内存趋势
vmstat 60 60 > mem_trend.log
# 每分钟记录一次,持续1小时
# 分析数据
awk '{if(NR>2) print NR,$4}' mem_trend.log
# free内存持续下降,确认内存泄漏
# 第2步:定位进程
ps aux --sort=-%mem | head
# 发现Python进程内存从500MB涨到8GB
# 第3步:使用pmap查看内存映射
pmap -x $(pgrep python)
# 发现heap区域异常增长
# 第4步:Python内存分析
# 安装memory_profiler
pip install memory-profiler
# 在代码中使用装饰器
from memory_profiler import profile
@profile
def suspicious_function():
# 函数代码
# 运行并分析
python -m memory_profiler app.py
# 输出显示某个列表持续增长
# Line 45: data_cache.append(large_object) # +500MB
# 第5步:代码分析
# 发现全局缓存无限增长,未设置上限
# 修复代码,添加LRU缓存
from functools import lru_cache
@lru_cache(maxsize=1000)
def cached_function(key):
# 函数代码
# 或手动管理缓存大小
if len(data_cache) > 10000:
data_cache = data_cache[-5000:]
# 第6步:验证
# 重启应用,持续监控
watch -n 60 "ps aux | grep python | grep -v grep | awk '{print \$6}'"
# 内存稳定在1GB左右,不再增长
根本原因: 全局缓存字典无限增长,未设置淘汰机制。
解决方案: 实现LRU缓存,限制缓存条目数量。
效果: 内存使用稳定,应用持续运行无OOM。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。