2、Linux性能工具集:perf、strace、ltrace、top、htop、vmstat、iostat、netstat、sar 的安装与基本使用
说实话,刚入行那会儿,我面对一台卡成PPT的服务器,第一反应就是重启。后来被前辈骂了一顿,才明白——不会用工具的性能工程师,跟赤手空拳上战场没啥区别。
这一章,我把Linux下最常用的9个性能工具给你捋一遍。每个工具我都踩过坑,有些坑现在想起来还肉疼。你跟着我走一遍,至少能少走半年弯路。
2.1 工具全景:一张图看懂谁该用在哪
先给你画个框架。这9个工具,说白了分三类:
- 系统级监控:top、htop、vmstat、iostat、sar —— 看整体健康度
- 进程级追踪:perf、strace、ltrace —— 钻到代码里看细节
- 网络诊断:netstat —— 查连接、查端口
我习惯把它们比作医院的检查设备:top是体温计,perf是CT机,strace是胃镜。各有各的用处,别拿体温计去查胃病。
核心原则:先宏观,后微观。别一上来就strace,先看看top和vmstat,锁定方向再深挖。
2.2 安装:别让工具成为第一道坎
很多新手卡在安装这一步。其实大部分工具都在系统源里,一行命令搞定。
Debian/Ubuntu 系
# 更新源
sudo apt update
# 一次性安装所有
sudo apt install -y linux-tools-common linux-tools-$(uname -r) \
strace ltrace htop sysstat net-tools
# 验证安装
perf --version
strace --version
htop --version
RHEL/CentOS 系
# 安装EPEL源(有些工具在EPEL里)
sudo yum install -y epel-release
# 安装工具集
sudo yum install -y perf strace ltrace htop sysstat net-tools
# 注意:CentOS 7 默认的 perf 版本较低,建议用 devtoolset 升级
sudo yum install -y centos-release-scl
sudo yum install -y devtoolset-9-perf
我的经验:在Ubuntu上装perf时,记得装对应内核版本的linux-tools。我见过有人装错版本,跑perf stat直接报"Kernel not supported",折腾了两小时才发现是版本不匹配。
2.3 top & htop:系统体检第一站
top是我每天打开终端第一个敲的命令。它告诉你:CPU谁在吃?内存谁在占?
top 基本操作
# 启动
top
# 常用交互快捷键(按一次就生效)
# 1 - 显示每个CPU核心的负载(默认只显示总负载)
# M - 按内存使用排序
# P - 按CPU使用排序
# k - 杀掉进程(输入PID和信号)
# q - 退出
我记得有一次线上告警,CPU飙到100%。我按1一看,8个核里7个空闲,就一个核跑满了。再按P排序,发现是个单线程的Python脚本在死循环。要是没按1,我可能还在傻傻地看总负载。
htop:top的颜值升级版
# 启动
htop
# 优势
# - 彩色显示,一眼看出CPU/内存/交换分区使用率
# - 支持鼠标操作(点一下就能排序)
# - 树形视图(F5),看清进程父子关系
# - 垂直/水平滚动,不怕进程太多
注意:htop虽然好看,但默认不显示线程。想看线程,按
H键切换。我曾经排查一个Java应用,htop里只看到一个进程,用H才发现里面藏了50多个线程在打架。
2.4 vmstat:系统瓶颈的X光机
vmstat是我个人最爱的工具之一。它用一行数据告诉你:系统到底卡在哪。
# 每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 102400 204800 102400 512000 0 0 10 20 500 1000 30 10 55 5 0
关键字段解读:
| 字段 | 含义 | 正常值 | 异常信号 |
|---|---|---|---|
| r | 运行队列(等待CPU的进程数) | < CPU核数*2 | > CPU核数*5,说明CPU不够用 |
| b | 阻塞队列(等待I/O的进程数) | 接近0 | 持续>0,说明磁盘或网络I/O是瓶颈 |
| si/so | 交换分区换入/换出 | 0 | 持续非0,说明内存不足 |
| wa | CPU等待I/O的时间百分比 | < 10% | > 30%,磁盘扛不住了 |
避坑指南:我曾经遇到一个案例,wa高达60%,但iostat显示磁盘利用率才20%。后来发现是磁盘控制器驱动有问题,导致I/O请求排队但没真正下发。所以,别只看一个指标,要交叉验证。
2.5 iostat:磁盘性能的显微镜
当vmstat告诉你wa偏高时,就该iostat上场了。
# 安装(sysstat包)
sudo apt install sysstat # Debian/Ubuntu
sudo yum install sysstat # RHEL/CentOS
# 每2秒输出一次,监控sda磁盘
iostat -x sda 2
# 输出示例
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.00 100.0 200.0 400.0 800.0 8.00 2.00 6.67 5.00 7.50 0.50 15.00
核心指标:
- %util:磁盘忙绿百分比。超过80%就要警惕,接近100%说明磁盘是瓶颈
- await:平均I/O等待时间(毫秒)。机械盘一般<10ms,SSD<1ms
- r_await / w_await:读写分别的等待时间。如果读等待高,可能是缓存命中率低;写等待高,可能是日志刷盘太频繁
我的经验:有一次数据库慢查询,iostat显示%util只有30%,但await高达50ms。仔细一看,r_await是5ms,w_await是95ms。原来是MySQL的binlog刷盘策略设成了每次提交都fsync,把写操作拖死了。改成组提交后,await降到5ms。
2.6 netstat:网络连接的侦探
netstat虽然老,但稳。排查端口冲突、连接数异常、半连接攻击,它都是首选。
# 查看所有监听端口
netstat -tlnp
# 查看所有连接(包括已建立的)
netstat -anp
# 统计各状态连接数
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 输出示例
ESTABLISHED 120
TIME_WAIT 350
CLOSE_WAIT 5
状态解读:
- TIME_WAIT:正常,主动关闭连接的一方会停留2MSL(约2分钟)。但如果超过几万个,说明短连接太多,考虑连接池或长连接
- CLOSE_WAIT:异常!对方关闭了连接,但你的程序没调用close()。这是代码bug,不修的话连接数会涨到上限
- SYN_RECV:收到SYN但没完成三次握手。如果数量很大,可能是SYN Flood攻击
我曾经接手过一个Java服务,CLOSE_WAIT飙到8000多,服务直接拒绝新连接。查代码发现是HTTP客户端的响应流没关闭。加了个try-with-resources,问题解决。记住:CLOSE_WAIT是代码问题,不是配置问题。
2.7 sar:历史数据的时光机
问题发生的时候你不在现场?sar可以帮你回放。
# 启动数据采集(sysstat服务)
sudo systemctl start sysstat
sudo systemctl enable sysstat
# 查看今天的CPU使用率历史
sar -u
# 查看今天的内存使用历史
sar -r
# 查看指定时间范围(例如10:00到11:00)
sar -u -s 10:00:00 -e 11:00:00
# 查看昨天的数据(默认保存7天)
sar -u -f /var/log/sysstat/sa$(date -d 'yesterday' +%d)
为什么重要? 很多性能问题是间歇性的。你盯着的时候它不出现,你一走它就崩。sar记录了系统每10分钟的快照,可以帮你找到规律——比如每天下午3点CPU飙升,是不是定时任务在作怪?
我的习惯:每台服务器我都开启sysstat,保留30天数据。有一次排查一个"每周一早上9点数据库变慢"的问题,sar显示那个时间点磁盘写IOPS翻了三倍。顺藤摸瓜,发现是备份脚本在跑。把备份时间挪到凌晨,问题解决。
2.8 perf:CPU性能的终极武器
perf是Linux内核自带的性能剖析工具。它能告诉你:CPU时间到底花在哪一行代码上。
# 统计CPU周期事件(默认)
perf stat ./my_program
# 采样分析(最常用)
perf record -g ./my_program # -g 记录调用栈
perf report # 查看热点函数
# 实时采样正在运行的进程(不重启)
perf top -p PID
实战案例:
# 假设有个程序跑得慢
perf record -g ./slow_program
perf report
# 输出中会显示类似:
# 45.67% slow_program [.] compute_hash
# 20.12% slow_program [.] memcpy
# 10.34% libc-2.31.so [.] __memmove_avx_unaligned_erms
# 看到没?45%的时间花在compute_hash上。点进去还能看到是哪一行。
避坑指南:perf record默认采样频率太高,可能影响程序性能。我一般加
-F 99(每秒采样99次),既够用又不至于拖慢程序。另外,perf需要root权限才能访问硬件计数器,记得加sudo。
2.9 strace & ltrace:系统调用和库调用的录音笔
strace跟踪系统调用,ltrace跟踪库函数调用。说白了,一个看内核,一个看用户态。
strace 基本用法
# 跟踪一个命令
strace -c ls # 统计各系统调用次数和时间
strace -t -T ls # -t 显示时间戳,-T 显示耗时
strace -e open,read ls # 只跟踪open和read调用
# 跟踪正在运行的进程
strace -p PID
# 输出到文件(避免刷屏)
strace -o trace.log ./program
经典场景:程序启动慢?strace一下,看看是不是在反复打开不存在的配置文件。
# 假设程序启动要10秒
strace -c ./slow_start
# 输出可能显示:
# % time seconds usecs/call calls errors syscall
# ------ ----------- ----------- --------- --------- ----------------
# 80.23 8.023456 8023 1000 0 read
# 10.12 1.012345 1012 1000 0 openat
# 5.34 0.534567 534 1000 0 stat
# 看到没?read调用花了8秒,而且调用了1000次。八成是在读一个很大的文件,或者读文件时阻塞了。
ltrace 基本用法
# 跟踪库函数调用
ltrace ./program
# 只跟踪特定库
ltrace -e 'libc.so*' ./program
# 统计调用次数和耗时
ltrace -c ./program
我曾经用strace抓到一个诡异的bug:一个C程序每隔几分钟就卡住5秒。strace显示卡住时在调用
gettimeofday(),但gettimeofday不应该阻塞啊!后来发现是NTP时间同步导致系统时间回跳,gettimeofday内部等待时钟修正。解决方案:禁用NTP的跳跃式同步,改用渐进式调整。
2.10 工具选择速查表
| 问题现象 | 首选工具 | 辅助工具 | 看什么指标 |
|---|---|---|---|
| CPU 100% | top/htop | perf top | 哪个进程/线程吃CPU |
| 系统响应慢 | vmstat 1 | sar -u | r队列、wa、上下文切换 |
| 磁盘I/O慢 | iostat -x 1 | sar -b | %util、await、svctm |
| 网络连接异常 | netstat -anp | ss -tlnp | CLOSE_WAIT、TIME_WAIT数量 |
| 程序启动慢 | strace -c | perf stat | 系统调用次数和耗时 |
| 内存泄漏 | top -M | sar -r | RES持续增长 |
| 历史性能回溯 | sar | - | 对比不同时间段的指标 |
最后说一句:工具是死的,人是活的。别指望一个工具解决所有问题。我见过有人用strace去查网络延迟,用netstat去查磁盘I/O——方向错了,再好的工具也白搭。先想清楚"我要查什么",再选工具。