Systat:4 款系统监控工具
当您只有一台游戏主机来排查性能问题时,本指南可能会派上用场。
vmstat
我弄明白vmstat的用法之后,发现它简直好用到让我离不开它了。好在它随处可见,所以我才有了它。Linux和Unix系统都有很多版本可供选择。
vmstat 几乎什么都做一点:内存、进程、I/O、交换空间、磁盘、CPU。
基本语法如下:
$ vmstat [options] <interval> <count>
vmstat 每隔interval秒打印一次更新,打印count行后停止。如果没有指定 count 行数,vmstat 将持续运行直到进程被终止。如果没有指定interval 值,则只打印一行。
# 1 update per second, 5 updates
$ vmstat 1 5
procs -----------memory---------- --swap- ---io--- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
4 0 0 4098084 375068 3462944 0 0 34 25 340 320 8 3 89 0 0
1 0 0 4098184 375068 3463264 0 0 0 0 1263 3198 4 3 93 0 0
0 0 0 4098436 375068 3462924 0 0 0 0 1141 2999 3 2 95 0 0
0 0 0 4097736 375076 3462916 0 0 0 0 2166 4414 5 4 92 0 0
0 0 0 4096476 375076 3462916 0 0 0 0 1103 3130 3 3 94 0 0
第一行中的数值是自系统启动以来的平均值,因此它通常与其他行中的数值明显不同。
除了内存和进程之外,所有数值均为上次更新的平均值。
内存和进程数(前 6 列)始终为瞬时值。内存以 KB 显示,但-S单位会发生变化,例如转换-S M为 MB。
如果您的 vmstat 版本支持-w,请使用它,它可以让表格更宽,更易于阅读。
那么每一列分别代表什么意思呢?
| 柱子 | 意义 | 单元 |
|---|---|---|
| r | 正在运行的进程数 | - |
| b | 阻塞的进程数 | - |
| 喷雾 | 使用的交换内存 | K |
| 自由的 | 空闲内存量 | K |
| 增幅 | 用于缓冲区的内存 | K |
| 缓存 | 用于缓存的内存 | K |
| 是 | 每秒从磁盘到内存的交换次数 | 1/秒 |
| 所以 | 每秒从内存到磁盘的交换次数 | 1/秒 |
| 双 | 每秒从块设备接收的块数 | 块/ |
| 波 | 每秒向块设备发送的块数 | 块/ |
| 在 | 每秒中断次数 | 1/秒 |
| CS | 每秒上下文切换次数 | 1/秒 |
| 我们 | CPU 用户时间 | 占总数的百分比 |
| sy | CPU 系统时间 | 占总数的百分比 |
| ID | CPU空闲时间 | 占总数的百分比 |
| 英石 | 从虚拟机窃取的 CPU 时间 | 占总数的百分比 |
以下是一些解读这些数值的指导原则:
- 首先检查si和so是否存在交换活动,这是性能杀手。
- 检查内存分配是否符合工作负载的需求。
- 持续的高负载可能表明CPU负载过高。
- 持续的高wa值表明可能存在I/O瓶颈负载。
- 如果这是一台虚拟机,并且st(窃取)持续处于较高水平很长时间,则主机系统可能过载或虚拟机配置不足。
-d获取自启动以来每个设备的 I/O 计数器。-p <PART>对于特定分区,我们也可以获得相同的信息。
-> vmstat -d 1
disk- ------------reads------------ ------------writes----------- -----IO------
total merged sectors ms total merged sectors ms cur sec
sda 154968 4762 5471678 52614 123981 67290 4139296 68873 0 45
sda 154968 4762 5471678 52614 123985 67305 4139440 68876 0 45
sda 187412 5295 5735630 57902 126252 67704 5888256 80177 0 51
...
列的阅读方式如下:
| 柱子 | 意义 |
|---|---|
| 全部的 | 读取/写入总数 |
| 合并 | 合并请求(将 N 个请求合并为一个 I/O) |
| 行业 | 读取/写入的扇区数量 |
| 多发性硬化症 | 阅读/写作所花费的毫秒数 |
| 库尔 | 正在运行的 I/O 操作数 |
| s | I/O 耗时秒数 |
我们还可以使用以下命令访问详细的缓存利用率报告-m,但这可能需要 root 权限才能正常工作。
$ vmstat -m
Cache Num Total Size Pages
ecryptfs_inode_cache 1544 1564 960 17
ecryptfs_file_cache 256 1024 16 256
ecryptfs_auth_tok_list_item 19 76 832 19
nf_conntrack_expect 0 0 216 18
nf_conntrack 101 200 320 25
fuse_request 80 80 400 20
fuse_inode 42 76 832 19
ext4_groupinfo_4k 1716 1736 144 28
ext4_inode_cache 325004 327150 1080 30
ext4_allocation_context 128 128 128 32
ext4_io_end 256 320 64 64
ext4_extent_status 156920 156978 40 102
mbcache 294 438 56 73
...
各列内容如下:
| 柱子 | 意义 |
|---|---|
| 缓存 | 缓存名称 |
| 数字 | 活动对象计数 |
| 全部的 | 对象总数 |
| 尺寸 | 每个物体的大小 |
| 页面 | 包含一个或多个活动对象的页面 |
vmstat 还提供以下一次性视图:
-s系统统计-D所有磁盘摘要-f叉子
iostat
iostat 显示 CPU 和磁盘 I/O 的综合统计信息。与 vmstat 一样,它支持设置间隔和计数。
# one update per second
$ iostat 1
Linux 4.19.8-arch1-1-ARCH (ix) 12/24/2018 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
12.14 0.03 5.66 0.03 0.00 82.14
Device tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 4.41 29.11 49.44 3409859 5790640
avg-cpu: %user %nice %system %iowait %steal %idle
5.56 0.00 3.79 0.00 0.00 90.66
Device tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.00 0.00 0.00 0 0
...
同样,第一份报告显示的是自系统启动以来的平均值(我们可以省略它-y)。而下面的报告显示的是自上一个时间间隔以来的比率。
我们可以选择仅查看 CPU 使用情况-c或仅查看磁盘使用情况-d。此外,-x还会显示扩展的 I/O 统计信息,并将-m单位更改为 MB。
-h改为更易于人类阅读的格式。
mpstat
mpstat 显示更详细的 CPU 统计信息。除了 vmstat 的计数器之外,我们还能获得一些其他信息。间隔和计数的处理方式也类似:
# 1 update per second
$ mpstat 1
Linux 4.19.8-arch1-1-ARCH (ix) 12/24/2018 _x86_64_ (4 CPU)
06:48:41 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
06:48:42 PM all 7.85 0.00 3.04 0.00 0.25 0.51 0.00 0.00 0.00 88.35
06:48:43 PM all 10.08 0.00 4.79 0.00 1.01 0.00 0.00 0.00 0.00 84.13
06:48:44 PM all 7.25 0.00 5.25 0.00 0.75 0.50 0.00 0.00 0.00 86.25
06:48:45 PM all 9.07 0.00 3.78 0.25 1.01 0.50 0.00 0.00 0.00 85.39
第一行是自系统启动以来的平均值。
我们可以选择仅显示某些 CPU 的活动-P,例如:-P 1,3
还有其他视图:-I ALL显示所有 CPU 中断,-n显示基于 NUMA 放置节点的 CPU 统计信息(用于-N指定要报告的节点)。甚至还有 JSON 输出-o JSON。
mpstat 显示总体 CPU 利用率,要跟踪单个进程,可以使用pidstat。
pidstat
这个命令与top 命令有些相似。pidstat 会每隔一段时间打印出正在运行的进程。我们还可以使用 pidstat 来跟踪特定的进程-p。线程信息则通过 pidstat 显示-t。
# track process CPU activity, thread view
$ pidstat -t -p 25809 1
Linux 4.19.8-arch1-1-ARCH (ix) 12/29/2018 _x86_64_ (4 CPU)
11:00:58 PM UID TGID TID %usr %system %guest %wait %CPU CPU Command
11:00:58 PM 980 25809 - 0.22 0.07 0.00 0.00 0.28 1 mysqld
11:00:58 PM 980 - 25809 0.00 0.00 0.00 0.00 0.00 1 |__mysqld
11:00:58 PM 980 - 25811 0.00 0.00 0.00 0.00 0.00 0 |__mysqld
11:00:58 PM 980 - 25812 0.00 0.00 0.00 0.00 0.00 3 |__mysqld
11:00:58 PM 980 - 25820 0.00 0.00 0.00 0.00 0.00 1 |__mysqld
11:00:58 PM 980 - 25834 0.02 0.01 0.00 0.01 0.02 3 |__mysqld
11:00:58 PM 980 - 25835 0.02 0.00 0.00 0.01 0.02 3 |__mysqld
11:00:58 PM 980 - 25836 0.01 0.00 0.00 0.01 0.02 2 |__mysqld
11:00:58 PM 980 - 25837 0.01 0.00 0.00 0.01 0.01 0 |__mysqld
-r显示每个进程的内存使用情况,这提供了一种快速检查内存泄漏的方法。
# track process memory activity
$ pidstat -r -p 27766 1
Linux 4.19.8-arch1-1-ARCH (ix) 12/30/2018 _x86_64_ (4 CPU)
09:42:59 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command
09:43:00 PM 1000 27766 0.00 0.00 689680 17128 0.15 mysqld
09:43:01 PM 1000 27766 0.00 0.00 689680 17128 0.15 mysqld
09:43:02 PM 1000 27766 0.00 0.00 689680 17128 0.15 mysqld
09:43:03 PM 1000 27766 0.00 0.00 689680 17128 0.15 mysqld
Average: 1000 27766 0.00 0.00 689680 17128 0.15 mysqld
pidstat 可以启动一个程序,-e并在执行过程中显示其活动。
除了 CPU 使用情况外,pidstat 还可以显示每个进程的 I/O 活动:
# per-process I/O
$ pidstat -d 1 5
Linux 4.20.0-arch1-1-ARCH (ix) 01/06/2019 _x86_64_ (4 CPU)
04:04:53 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
04:04:54 PM 1000 14423 276.00 197888.00 0.00 1 dd
04:04:55 PM 1000 14423 0.00 218880.00 0.00 0 dd
04:04:56 PM 1000 14423 0.00 224664.00 0.00 0 dd
04:04:57 PM 1000 14423 0.00 230428.00 0.00 0 dd
04:04:59 PM 1000 14423 0.00 192520.00 0.00 0 dd
Average: 1000 14423 46.00 207763.33 0.00 0 dd
如果 pidstat 输出负值,则表示它没有足够的权限访问该进程。
尝试切换到运行该进程的用户(或者以 root 用户身份运行,这应该总是可行的)。
pidstat 支持所有这些视图:
-dI/O统计信息-uCPU统计信息-R流程优先级-r内存利用率-s堆栈利用率-t线程统计-w任务切换-v文件描述符
把所有东西整合起来
这些程序相互补充。它们如何协同工作呢?
假设我们想找出我的机器运行缓慢的原因。
我首先要检查的是 vmstat:
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 12 773184 3782540 161528 3176304 0 0 1184 38944 2888 9877 20 5 1 74 0
2 9 773184 3745748 161528 3213272 0 0 2660 36868 2876 7426 18 7 1 73 0
0 11 773184 3630836 161540 3326616 0 0 2688 43052 2959 7064 23 5 1 70 0
2 11 771648 2297092 161792 4873416 0 0 2672 40960 3034 7547 23 6 2 69 0
1 11 771648 2255008 161796 4915000 0 0 2088 38912 2939 7370 24 6 2 67 0
0 11 771648 2142616 161796 4992940 0 0 2148 38916 2976 8061 31 6 1 63 0
1 10 771648 2100532 161804 5034252 20 0 1608 41012 3919 9665 34 11 1 54 0
0 11 819776 149836 157540 6949188 0 0 1920 12292 2702 5527 6 4 0 90 0
你看到了什么?阻塞数(b)持续偏高,内存利用率上升,没有交换……这很好。
嗯。CPU等待时间一直很高(哇)。
这些都是 I/O 瓶颈的迹象,CPU 花费大量时间等待磁盘。
mpstat 显示什么?
$ mpstat 1
Linux 4.20.0-arch1-1-ARCH (ix) 01/06/2019 _x86_64_ (4 CPU)
01:34:49 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
01:34:50 PM all 24.54 0.00 4.22 68.87 1.06 1.06 0.00 0.00 0.00 0.26
01:34:51 PM all 19.05 0.00 3.44 74.87 1.06 0.53 0.00 0.00 0.00 1.06
01:34:52 PM all 19.37 0.00 3.14 74.61 0.79 1.05 0.00 0.00 0.00 1.05
01:34:54 PM all 22.08 0.00 3.12 62.86 0.52 1.04 0.00 0.00 0.00 10.39
又出现了,iowait 值很高。磁盘肯定出了问题。
我们来试试 iostat:
$ iostat -x 1 -y
Linux 4.20.0-arch1-1-ARCH (ix) 01/06/2019 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 0.00 0.00 0.00 0.00
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
sda 54.00 0.00 2532.00 0.00 0.00 0.00 0.00 0.00 0.57 0.00 0.02 46.89 0.00 0.06 0.30
dm-0 54.00 0.00 2532.00 0.00 0.00 0.00 0.00 0.00 0.50 0.00 0.03 46.89 0.00 0.24 1.30
sdd 1.00 347.00 4.00 39512.00 0.00 0.00 0.00 0.00 53.00 5.42 0.99 4.00 113.87 2.86 99.40
avg-cpu: %user %nice %system %iowait %steal %idle
23.90 0.00 6.49 68.31 0.00 1.30
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
sda 69.00 0.00 2636.00 0.00 2.00 0.00 2.82 0.00 0.58 0.00 0.06 38.20 0.00 0.29 2.00
dm-0 71.00 0.00 2636.00 0.00 0.00 0.00 0.00 0.00 1.03 0.00 0.07 37.13 0.00 0.32 2.30
sdd 0.00 340.00 0.00 38672.00 0.00 0.00 0.00 0.00 0.00 5.84 0.99 0.00 113.74 2.92 99.30
SSD设备上的写入操作相当多。更糟糕的是,设备利用率 (%util) 已达到 100%,设备已饱和。
(%util 仅对机械硬盘有意义,RAID 或 SSD 的容量不同)
所以问题似乎与SDD有关。
我们可以查看哪些进程正在进行 I/O 操作吗?
$ sudo pidstat -d 1
Linux 4.20.0-arch1-1-ARCH (ix) 01/06/2019 _x86_64_ (4 CPU)
01:36:25 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
01:36:26 PM 0 2546 3.81 0.00 0.00 100 kworker/u8:3+flush-8:48
01:36:26 PM 0 2799 0.00 38.10 0.00 48 jbd2/sdd1-8
01:36:26 PM 980 3435 1474.29 36323.81 0.00 0 mysqld
01:36:26 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
01:36:27 PM 0 2546 0.00 0.00 0.00 99 kworker/u8:3+flush-8:48
01:36:27 PM 980 3435 2524.00 35096.00 0.00 0 mysqld
我们发现了一个 MySQL 服务器、一个正在刷新数据的内核线程和 jbd2(文件系统日志)。
啊哈!我们找到了导致所有麻烦的 I/O 的原因。要继续调查,我们需要进入数据库,但这篇文章已经太长了。如果你好奇的话,根本原因是某些错误的查询创建了临时表。
相关链接
- 手册页