惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
GbyAI
GbyAI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
量子位
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
CERT Recently Published Vulnerability Notes
Recent Announcements
Recent Announcements
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
P
Privacy International News Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 叶小钗
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
T
The Exploit Database - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
P
Proofpoint News Feed
NISL@THU
NISL@THU
博客园 - Franky
C
Cybersecurity and Infrastructure Security Agency CISA
The Register - Security
The Register - Security
M
MIT News - Artificial intelligence
Know Your Adversary
Know Your Adversary
A
Arctic Wolf
F
Full Disclosure
T
Threat Research - Cisco Blogs
P
Privacy & Cybersecurity Law Blog
The Hacker News
The Hacker News
博客园 - 【当耐特】
D
Docker
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Jina AI
Jina AI
Help Net Security
Help Net Security
V
Visual Studio Blog
小众软件
小众软件
B
Blog
Vercel News
Vercel News
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
Forbes - Security
Forbes - Security
N
Netflix TechBlog - Medium
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic

博客园 - 于光远

泛型编程 分区理论知识整理 SPI协议及驱动开发框架 I2C协议及驱动开发框架 使用qemu 加载linux-6.18.1内核 linux 内核 策略模式 单例模式 C++模板元编程实现序列化与反序列化 引用 bootchart linux 脚本打印时间 接口编程 不定参数解析,结合tuple 独立于main运行的程序 类模板继承 std::ostream & operator<< Flash HIDL --HelloWorld
Linux性能分析:从监控到优化的完整工具链
于光远 · 2025-11-05 · via 博客园 - 于光远

https://mp.weixin.qq.com/s/YC880xAiCdsRbbdpaRWXMA?mpshare=1&scene=1&srcid=1102k8a0975YxpKRNMJgC2he&sharer_shareinfo=9ea5ee22f4579d0017aeb6a295d5b7a4&sharer_shareinfo_first=9ea5ee22f4579d0017aeb6a295d5b7a4&color_scheme=light#rd

一、系统整体监控:建立性能基线

1. vmstat - 虚拟内存统计的瑞士军刀

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

关键指标解析:

  • • r (运行队列): 值为2表示有2个进程等待CPU,持续大于CPU核心数说明CPU不足
  • • b (阻塞进程): 等待I/O的进程数,持续高值表示I/O瓶颈
  • • swpd (交换内存): 使用的swap空间,非零且持续增长预示内存不足
  • • si/so (swap in/out): 每秒从/向磁盘swap的内存量,持续非零表示内存压力大
  • • bi/bo (块设备I/O): 每秒读写的块数,突然增大提示磁盘I/O激增
  • • us/sy/id/wa: CPU时间占比,wa(等待I/O)持续>20%说明I/O瓶颈严重

实战案例 - 内存泄漏检测:

# 监控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列持续下降,cachebuff不变,可能存在内存泄漏。

2. iostat - 深入磁盘I/O性能

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

关键指标:

  • • r/s, w/s: 每秒读写请求数,突增表示负载激增
  • • await: 平均I/O请求等待时间(毫秒),>20ms需关注,>100ms严重
  • • util: 设备利用率,持续>80%表示设备饱和,可能成为瓶颈
  • • avgqu-sz: 平均请求队列长度,>2表示设备过载

实战案例 - 数据库慢查询诊断:

# 持续监控,记录I/O峰值
iostat -x 1 60 | tee iostat_db.log

# 同时抓取数据库慢查询日志时间戳
# 对比时间点,定位是否I/O导致查询变慢

某电商系统案例:发现订单查询缓慢,通过iostat发现await达到150ms,util持续95%。进一步分析发现订单表未建索引,全表扫描导致大量随机I/O。添加索引后,await降至5ms,查询速度提升30倍。

3. dstat - 多维度综合监控

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同时监控发现:

  • • CPU usr达到95%,转码进程占用高
  • • 磁盘写入突增至800MB/s,输出文件导致
  • • 网络发送达到网卡上限(1Gbps),传输转码文件

问题定位:转码、写盘、网络传输同时进行,资源竞争严重。优化方案:转码完成后再传输,错峰处理,性能提升40%。

二、进程级精准监控

1. top/htop - 实时进程监控

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)

2. pidstat - 进程资源详细统计

pidstatsysstat包的一部分,能精确追踪进程级别的资源消耗。

核心用法:

# 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
  • • kB_rd/s: 每秒读取的KB数
  • • kB_wr/s: 每秒写入的KB数
  • • kB_ccwr/s: 取消的写入(通常因为覆盖)

实战案例 - 定位异常进程:

某生产环境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
# 定位到异常正则表达式导致的回溯爆炸

3. iotop - 磁盘I/O实时监控

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倍

三、网络与连接分析

1. netstat - 网络连接状态查询

实用命令集:

# 显示所有TCP连接
netstat -ant

# 显示监听端口
netstat -tunlp

# 显示网络统计
netstat -s

# 显示路由表
netstat -r

# 持续监控连接数变化
watch -n 1 "netstat -an | grep ESTABLISHED | wc -l"

连接状态解读:

  • • ESTABLISHED: 已建立连接
  • • TIME_WAIT: 连接关闭,等待确认,过多提示连接频繁
  • • CLOSE_WAIT: 远程端关闭,本地未关闭,可能代码未正确关闭连接
  • • SYN_SENT: 尝试建立连接
  • • SYN_RECV: 收到连接请求,可能遭受SYN攻击

实战案例 - 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以下

2. ss - netstat的现代替代品

ssnetstat更快,信息更丰富。

高级用法:

# 显示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

四、深度调试与追踪

1. strace - 系统调用追踪神器

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倍

2. lsof - 列出打开文件

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

五、系统级性能分析

1. perf - Linux性能分析利器

参考这篇文章: Linux性能分析:perf火焰图以及性能开销

2. mpstat - 多核CPU监控

在多核系统中,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倍

六、综合实战案例

案例1:Web服务器响应缓慢完整排查

症状: 用户反馈网站打开慢,响应时间从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%。

案例2:内存泄漏导致系统OOM

症状: 应用运行几天后被系统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。