Linux问题诊断工具箱

前言

当应用层面没有足够的上下文信息做性能诊断时,利用Linux内置的工具命令协助性能诊断时必备的技能之一,本文总结一些比较常用的Linux性能诊断命令。Linux操作系统的可观测行很好,从CPU、磁盘、网卡、文件系统到内存都有对应的诊断工具。
image.png

工具安装与准备

平时使用的工具最好是优先掌握Linux系统内置的命令(无需额外安装)以及各大主流Linux发行版包管理中都可以下载到的工具。

sysstat工具集

sysstat是一个工具集合,一般通过yum或者apt-get即可直接安装

1
2
3
4
## 安装
yum install sysstat
## 确认安装版本
sar -V

sysstat工具包包含的工具:

  • iostat 工具提供CPU使用率及硬盘吞吐效率的数据; #比较核心的工具
  • mpstat 工具提供单个处理器或多个处理器相关数据;
  • pidstat: 关于运行中的进程/任务、CPU、内存等的统计信息
  • sar 工具负责收集、报告并存储系统活跃的信息; #统计数据的核心工具
  • sa1 工具负责收集并存储每天系统动态信息到一个二进制的文件中。它是通过计划任务工具cron来运行,是为sadc所设计的程序前端程序;
  • sa2工具负责把每天的系统活跃性息写入总结性的报告中。它是为sar所设计的前端 ,要通过cron来调用
  • sadc 是系统动态数据收集工具,收集的数据被写一个二进制的文件中,它被用作sar工具的后端;
  • sadf 显示被sar通过多种格式收集的数据;
  • nfsiostat: NFS(Network File System)的I/O统计信息。
  • cifsiostat: CIFS(Common Internet File System)的统计信息

bcc-tools

bcc工具集,基于bcc配合eBPF的工具集合。注意内核版本太低不太可用,最起码4.1以上,最好内核版本4.9及以上。更多使用示例的话可以参考bcc项目代码

由于bcc-tools本质是eBPF程序。更多eBPF tool有兴趣的话可以参考Linux Extended BPF (eBPF) Tracing Tools。 BPF实现的工具如果熟练使用,基本整个操作系统的观测程度就非常高了,下图展示了操作系统各个层面支持的BPF工具。不过我们能直接安装好的bcc-tools是这边工具的一个子集。
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Ubuntu

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD

echo "deb https://repo.iovisor.org/apt/$(lsb_release -cs) $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/iovisor.list

sudo apt-get update
c
sudo apt-get install bcc-tools libbcc-examples linux-headers-$(uname -r)

export PATH=$PATH:/usr/share/bcc/tools



# CentOS

yum install bcc-tools

export PATH=$PATH:/usr/share/bcc/tools

以下是装好有/usr/share/bcc/tools可以看到一些命令。本文篇幅有限,会挑选几个自己觉得比较重要的几个来说明下。
image.png

全局概览统计信息查看工具

top

top包含信息比较完整,可以通过-Hp查看特定进程的CPU使用情况,也可以查看实时的cpu load的实时变化情况,是最为常用的命令之一。

vmstat

适合查看整体的情况

1
vmstat 1

image.png

sar

sar工具包含在sysstat工具中,是sysstat中很强大的工具。其不同的参数可以对各个组件获取统计信息,最重要的是,其能查看历史数据。下文中谈到具体组件时会演示如何使用sar。
image.png

pidstat

也是可以看cpu、内存、IO的工具命令。相比sar的优点是他可以看到进程级别的信息,在排查特定进程某个指标时会特别有用。

CPU相关诊断工具

mpstat与/proc/stat

mp是multi processor的缩写。mpstat主要获取多核CPU性能的统计信息。这些信息来自/proc/stat。常用的用法如下。

1
2
3
## -P: {|ALL} 表示监控哪个CPU, cpu在[0,cpu个数-1]中取值 
## 展示每个核的统计情况
mpsata -P ALL 1
  • %user:在internal时间段里,用户态的CPU时间(%),不包含nice值为负进程 (usr/total)*100
  • %nice:在internal时间段里,nice值为负进程的CPU时间(%) (nice/total)*100
  • %sys :在internal时间段里,内核时间(%) (system/total)*100
  • %iowait:在internal时间段里,硬盘IO等待时间(%) (iowait/total)*100
  • %irq:在internal时间段里,硬中断时间(%) (irq/total)*100
  • %soft:在internal时间段里,软中断时间(%) (softirq/total)*100
  • %idle:在internal时间段里,CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间(%) (idle/total)*100

/proc/interrtupts和/proc/softirqs

一般全局如果发现CPU中断有些问题,比如中断过高或者不均匀。我们还需要定位具体是哪个外部设备引发的中断。配合watch命令可以每隔一定时间刷新,观察数值变化确定是具体什么设备和操作产生了较大的中断开销。

1
watch -n1  -d cat /proc/softirqs

lscpu和/proc/cpuinfo

查看CPU个数和缓存大小等信息

火焰图(flamegraph)

cpu热点函数很适合通过火焰图来分析。随着eBPF特性在Linux内核的支持,现在也支持采用eBPF的方式生成火焰图了,更加高效不用生成perf.data,直接在内核内统计。

考虑到兼容性,一般用perf生成火焰图使用范围更加宽。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
### Linux 内核2.6以上使用perf
## 有些发行版不支持perl得安装下,如果没找到说明没必要安装
yum -y install perl-open.noarch
yum -y install perf
git clone --depth 1 https://github.com/brendangregg/FlameGraph
cd FlameGraph
## 以99HZ频率采样整个系统,持续30秒
perf record -F 99 -a -g --sleep 30
## 或者针对一个具体进程采样
perf record -F 99 -p PID -g -- sleep 10
## 该文件可以用FlameScope访问
perf script --header > out.perf01
##
./stackcollapse-perf.pl < out.perf01 | ./flamegraph.pl > perf.svg

## 另外也可以直接通过report在命令行看占用情况(一般排查感觉用report更加快捷清晰)
perf report -n --stdio

4.9以上支持BPF的Linux内核可以使用BPF的方式,性能更好

1
2
3
4
### Linux内核4.9+以上使用BPF
git clone --depth 1 https://github.com/brendangregg/FlameGraph
git clone --depth 1 https://github.com/iovisor/bcc
./bcc/tools/profile.py -dF 99 30 | ./FlameGraph/flamegraph.pl > perf.svg

一般线上排查问题只关注一个进程的时候直接用perf record也挺方便,因为本身东西也不多
image.png

cpu相关的sar命令

其实有多个cpu相关的命令,但是从实用性来说,我觉得记忆如下两个就够了。sar用来看CPU上下文切换和中断的用mpstat看更加清楚。其中saq -q用来看排队还是挺实用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 间隔1秒3次,输出进程的cpu使用率,u代表utilization
sar -u 1 3

21时26分47秒 CPU %user %nice %system %iowait %steal %idle
21时26分48秒 all 16.33 0.00 2.04 0.00 0.00 81.63
21时26分49秒 all 24.62 0.00 3.02 0.00 0.00 72.36

# q代表queue
sar -q 1 3

## 结果中
runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked
05:10:01 PM 0 361 0.29 1.68 2.14 0

忘记字段含义的话直接man sar然后搜索下字段名字就可以确认
image.png

pidstat

直接使用该命令等价于使用**pidstat -u -p ALL,**配合grep可以查看各个进程的cpu使用率情况。

内存相关诊断工具

内存可以监控的包含很多种类。
image.png

内存相关的sar命令

sar命令很强,可以看各种细致的进程内存使用情况。不过一般熟悉-r和-B即可。-r看内存利用率,-B主要看内存页的统计信息,内存页的读写、缺页中断(page fault)等信息。
image.png

pidstat -r查看ram内存统计

配合grep可以只看特定进程的
image.png

pmap查看进程内存映射

可以看到进程具体内存映射情况,用于定位进程的内存瓶颈。

1
2
## 查看当前进程内存映射,占用最多的10个
pmap -x ${PID} | sort -r -n -k3 | head -n 10

找到异常的内存块要看内容可以配合gdb命令把内存块dump出来。步骤如下:

  • 通过smaps可以输出进程使用的内存块详细信息,包括地址范围和来源:
1
2
cat /proc/<pid>/smaps > smaps.txt

  • 找到包含异常内存地址的地址范围
  • gdb attach
  • dump指定内存地址到指定的目录下,参数的地址需要在smaps拿到地址前加上0x
1
dump memory /tmp/0x7fb9b0000000-0x7fb9b3ffe000.dump 0x7fb9b0000000 0x7fb9b3ffe000
  • 显示长度超过10字符的字符串
1
2
strings -10 /tmp/0x7fb9b0000000-0x7fb9b3ffe000.dump

memleak查看内存泄露

使用案例可以参考memleak_example.txt,基本用法其实还是比较简单的

1
./memleak -p ${PID}

cachestat、cachetop查看page cache命中率情况

cachetop查看进程全局命中情况,排查或者优化一些读写性能的时候可以考虑追踪下page cache的情况
image.png

cachestat则看系统全局的命中率:
image.png

磁盘I/O

pidstat -d

查看进程的I/O可以用

1
pidstat -d

iostat

这个效果和sar -d的效果几乎一样,记住用一个就够了,我们用sar

sar

1
2
# sar -d 1

image.png

biosnoop追踪数据块实时写入情况

bcc-tool工具之一,实时追踪块设备写入,可以用来哪些行为导致磁盘性能劣化。

1
./usr/share/bcc/tools/biosnoop

image.png

biolatency块设备延迟统计直方图

1
./usr/share/bcc/tools/biolatency

默认是微秒,可以-m指定看毫秒的结果
image.png

网络相关

netstat

查看connection和端口占用很常用。不过现在有ss了,推荐用ss性能更好

1
netstat -antlp| grep ${PID}

ss

1
ss -antp| grep ${PID}

sar -n DEV 查看网络I/O

dev即指的是network device。这边-n后面支持的类型有:DEV, EDEV, NFS, NFSD, SOCK, IP, EIP, ICMP, EICMP, TCP, ETCP, UDP, SOCK6, IP6, EIP6, ICMP6, EICMP6 and UDP6. 一般常用的我们记住下面两个就够用了

1
2
3
4
### 查看网络I/O
sar -n DEV 3 1
### 查看TCP流量
sar -n TCP,ETCP 3 1

DEV的结果
image.png

tcpretrans查看重连

1
./usr/share/bcc/tools/tcpretrans

相比sar查看重传,tcpretrans能比较精确定位到产生重传的进程,定位更加直接。
image.png

ethtool查看网卡情况

1
2
3
4
5
## 查看网卡基本情况
ethtool eth0
## 查看网卡ring buffer
ethtool -g eth0

mtr命令查看每一跳的丢包情况

默认没有需要安装下,yum install mtr

1
2
3
4
5
6
7
8
9
10
11
mtr -r baidu.com
### 结果如下
Start: 2023-01-18T23:06:05+0800
HOST: wanshao-blog-ecs Loss% Snt Last Avg Best Wrst StDev
1.|-- 10.33.244.26 0.0% 10 1.6 1.7 1.5 1.9 0.1
2.|-- 11.73.8.110 10.0% 10 2.5 2.1 1.8 2.5 0.2
3.|-- 10.54.165.194 0.0% 10 1.6 1.6 1.5 1.9 0.1
4.|-- 11.94.128.178 0.0% 10 3.9 4.0 3.7 4.3 0.2
5.|-- 10.102.41.153 0.0% 10 4.2 4.3 4.2 4.8 0.2
6.|-- 122.224.214.65 20.0% 10 4.2 4.2 4.1 4.4 0.1
7.|-- 220.191.199.117 0.0% 10 7.0 7.0 7.0 7.0 0.0

traceroute查看每一跳延迟

yum install traceroute先安装下

1
traceroute -n 180.101.50.172

image.png

ifconfig查看网卡流控队列、drop情况

网卡性能不足有时候也会导致网络丢包,可以看看drop情况。不过一般千兆网卡不太可能被打满
image.png

文件系统

/proc/${pid}/fd 查看进程文件句柄占用

文件句柄没有及时关闭这类问题也会发生,一般是用于没有正确关闭流导致。

1
ls -l /proc/${pid}/fd|wc -l

open系统调用追踪opensnoop

bcc-tool工具之一,需要先安装bcc-tool。这个用来看实时的进程fd占用和打开文件的情况很有用。

1
./usr/share/bcc/tools/opensnoop -p ${pid}

ext4slower查看ext4文件系统的slow write

bcc-tool工具之一,需要先安装bcc-tool。查看ext4文件系统实时的慢写入很有用。

1
2
## 第一个数字代表阈值毫秒,查询写入延迟2毫秒以上的行为
./usr/share/bcc/tools/ext4slower 2 -p ${pid}

cachestat查看文件系统缓存命中

1
./usr/share/bcc/tools/cachestat

image.png

其他

内核日志dmesg

dmesg主要用来查看内核环形缓冲区的日志。kernel ring buffer是个固定大小的空间,在系统引导时,内核将与硬件和模块初始化相关的信息填到这个缓冲区中。常见用于排查的问题例如:

  • 系统启动与硬件初始化相关问题
  • 硬件的异常行为,比如网络sync flood、oom_killer执行(本质是内核关联RAM的行为)

常用命令如下

1
2
3
4
5
6
# 查看系统层面warning error级别日志
dmesg -T --level=err,warn
## 查看内存、DMA、USB、TTY等不同类别的日志
dmesg -T | grep -E "memory|dma|usb|tty"
## 查看oom_killer是否有执行
dmesg -T | grep -i oom_killer

execsnoop查看实时进程启动

排查一些不符合预期的进程拉起会比较有用。不过没有跟踪fork/clone/vfork,子进程创建不监控。

1
./usr/share/bcc/tools/execsnoop

实际应用

网卡软中断不均衡导致丢包

以前在阿里工作时就遇到过双十一压测性能上不去有丢包导致的网络重传,最后发现是多队列网卡软中断不均衡导致的,后来通过irq亲缘绑定解决的。这个可以参考网卡软终端不均衡问题及解决方案
查找网卡发送、接收队列的中断号,查看亲缘绑定。
image.png

参考资料