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}

磁盘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

文件系统

/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

参考资料