linux中time命令详解、脚本监控记录系统硬盘io值、定位linux系统中await值过高占用的盘、定位占用硬盘IO高的程序、iotop命令说明、lsof使用说明【可定位端口所占用程序等】

文章说明

  • 我为什么会写这篇文章呢,是因为我们生产环境中有一台虚拟机,出现了一个问题,vi编辑的时候,保存需要挺长时间的,少则几秒,多则几分钟也有可能才能保存成功【但这个只是针对系统盘vda,外挂盘vdb却是正常的,不知道是不是系统出问题了】。

    • 其实这不是第一次出现了,之前出现过一次,但没能解决。
    • 这是第二次台机子出现这种问题,这次我决定,深入研究一下这个东西,所以这次需要嵌套使用的东西有点点多~,你如果没有基础,这篇文章看着可能有点点费劲。
  • 注:我上面说的,这种情况仅仅是针对vi编辑保存的时候出现问题,系统其他操作没有任何问题,并且也不影响系统的正常使用,就是vi编辑保存的时候需要费挺长时间,并不是一直这样,而是偶发性的。【并且仅仅是针对系统盘,外挂盘vi保存是正常的】

  • 我下面所有用到的东西,都是为了排查vi保存慢的问题,是联合使用的哈,并不是一些零碎的知识,所以,再这篇文章中存在的东西,都是合理的,有疑问可以留言私信,一起学习。

linux中的time命令

说明&常规用法

  • time命令用于统计给定命令所花费的总时间。

  • 语法

time [options] COMMAND [arguments]
  • 参数:

    • -o 或 --output=FILE:设定结果输出档。这个选项会将 time 的输出写入 所指定的档案中。如果档案已经存在,系统将覆写其内容。
    • -a 或 --append:配合 -o 使用,会将结果写到档案的末端,而不会覆盖掉原来的内容。
    • -f FORMAT 或 --format=FORMAT:以 FORMAT 字串设定显示方式。当这个选项没有被设定的时候,会用系统预设的格式。不过你可以用环境变数 time 来设定这个格式,如此一来就不必每次登入系统都要设定一次。
    • -p or --portability:这个选项会自动把显示格式设定成为: real %e user %Usys %S:这么做的目的是为了与 POSIX 规格相容。
    • -v or --verbose:这个选项会把所有程序中用到的资源通通列出来,不但如一般英文语句,还有说明。对不想花时间去熟习格式设定或是刚刚开始接触这个指令的人相当有用。
  • 系统一般自带有这个命令,灭有的话直接安装即可
    yum -y install time

  • 实例【其实time主要就是查看一下命令执行时间罢了,就如下】
    当测试一个程序或比较不同算法时,执行时间是非常重要的,一个好的算法应该是用时最短的。所有类UNIX系统都包含time命令,使用这个命令可以统计时间消耗。例如:

[root@xz-qklxi-gs-06 sh]# time ls
202204151744  a  io  io.sh  psinfo  ps.sh

real    0m0.003s
user    0m0.000s
sys     0m0.003s
[root@xz-qklxi-gs-06 sh]# 
  • 输出的信息分别显示了该命令所花费的real时间、user时间和sys时间。
    • real时间是指挂钟时间,也就是命令开始执行到结束的时间。这个短时间包括其他进程所占用的时间片,和进程被阻塞时所花费的时间。
    • user时间是指进程花费在用户模式中的CPU时间,这是唯一真正用于执行进程所花费的时间,其他进程和花费阻塞状态中的时间没有计算在内。
    • sys时间是指花费在内核模式中的CPU时间,代表在内核中执系统调用所花费的时间,这也是真正由进程使用的CPU时间。

bash中使用time,将运行记录追加到文件中,-f后的参数说明

  • shell内建也有一个time命令,当运行time时候是调用的系统内建命令,应为系统内建的功能有限,所以需要时间其他功能需要使用time命令可执行二进制文件/usr/bin/time【如果没有这个文件,需要先执行yum -y install time】。
# 是的,能执行time不代表有time文件,所以需要安装。
[root@xz-qklxi-gs-06 sh]# time ls
202204151744  a  io  io.sh  psinfo  ps.sh

real    0m0.004s
user    0m0.001s
sys     0m0.003s
[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# /usr/bin/time ls
-bash: /usr/bin/time: No such file or directory
[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# yum -y install time
Loaded plugins: fastestmirror
http                                                                                                                 | 2.9 kB  00:00:00     
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package time.x86_64 0:1.7-45.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

============================================================================================================================================
 Package                        Arch                             Version                               Repository                      Size
============================================================================================================================================
Installing:
 time                           x86_64                           1.7-45.el7                            http                            30 k

Transaction Summary
============================================================================================================================================
Install  1 Package

Total download size: 30 k
Installed size: 47 k
Downloading packages:
time-1.7-45.el7.x86_64.rpm                                                                                           |  30 kB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : time-1.7-45.el7.x86_64                                                                                                   1/1 
  Verifying  : time-1.7-45.el7.x86_64                                                                                                   1/1 

Installed:
  time.x86_64 0:1.7-45.el7                                                                                                                  

Complete!
[root@xz-qklxi-gs-06 sh]# /usr/bin/time 
  • 使用-o选项将执行时间写入到文件中:/usr/bin/time -o 后面跟存放文件 最后放执行命令或语句
[root@xz-qklxi-gs-06 sh]# /usr/bin/time -o test.txt ls
202204151744  a  io  io.sh  psinfo  ps.sh  test.txt
[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# cat test.txt 
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 964maxresident)k
0inputs+0outputs (0major+294minor)pagefaults 0swaps
[root@xz-qklxi-gs-06 sh]# 
  • 使用-a选项追加信息:也就是多了输出内容嘛。-a必须再-o前面
[root@xz-qklxi-gs-06 sh]# /usr/bin/time -a -o test.txt df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G  7.1G   43G  15% /
devtmpfs        7.8G     0  7.8G   0% /dev
tmpfs           7.8G     0  7.8G   0% /dev/shm
tmpfs           7.8G   33M  7.8G   1% /run
tmpfs           7.8G     0  7.8G   0% /sys/fs/cgroup
overlay          50G  7.1G   43G  15% /var/lib/docker/overlay2/13a54473c3755cd1b603726a3bd3d9ab04341976f3192c5bb1f5985d9bddc4b9/merged
tmpfs           1.6G     0  1.6G   0% /run/user/0
[root@xz-qklxi-gs-06 sh]# cat test.txt 
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 964maxresident)k
0inputs+0outputs (0major+294minor)pagefaults 0swaps
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 928maxresident)k
0inputs+0outputs (0major+279minor)pagefaults 0swaps
[root@xz-qklxi-gs-06 sh]# 
  • 使用-f选项格式化时间输出:
    -f选项后的参数:

    • %E real时间,显示格式为[小时:]分钟:秒
    • %U user时间。
    • %S sys时间。
    • %C 进行计时的命令名称和命令行参数。
    • %D 进程非共享数据区域,以KB为单位。
    • %x 命令退出状态。
    • %k 进程接收到的信号数量。
    • %w 进程被交换出主存的次数。
    • %Z 系统的页面大小,这是一个系统常量,不用系统中常量值也不同。
    • %P 进程所获取的CPU时间百分百,这个值等于user+system时间除以总共的运行时间。
    • %K 进程的平均总内存使用量(data+stack+text),单位是KB。
    • %w 进程主动进行上下文切换的次数,例如等待I/O操作完成。
    • %c 进程被迫进行上下文切换的次数(由于时间片到期)。
  • 如:

# 直接打印
[root@xz-qklxi-gs-06 sh]# /usr/bin/time -f "usertime: %U systime: %S num: %K" ls
202204151744  a  io  io.sh  psinfo  ps.sh  test.txt
usertime: 0.00 systime: 0.00 num: 0
[root@xz-qklxi-gs-06 sh]# 

# 可以加\t制表符
[root@xz-qklxi-gs-06 sh]# /usr/bin/time -f "\t%U user,\t%s system" date
Tue Apr 19 09:28:32 UTC 2022
        0.00 user,      0 system
[root@xz-qklxi-gs-06 sh]# 

# 也可以追加到文件
[root@xz-qklxi-gs-06 sh]# > test.txt 
[root@xz-qklxi-gs-06 sh]# /usr/bin/time -f "usertime: %U systime: %S num: %K" -o test.txt ls
202204151744  a  io  io.sh  psinfo  ps.sh  test.txt
[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# cat test.txt 
usertime: 0.00 systime: 0.00 num: 0
[root@xz-qklxi-gs-06 sh]#

高阶用法

  • Linux time命令的用途,在于量测特定指令执行时所需消耗的时间及系统资源等资讯。
    例如 CPU 时间、记忆体、输入输出等等。需要特别注意的是,部分资讯在 Linux 上显示不出来。这是因为在 Linux 上部分资源的分配函式与 time 指令所预设的方式并不相同,以致于 time 指令无法取得这些资料。

time 命令详细输出指标介绍

  • 其实上面使用的 time 真的是“巧妇难为无米之炊”,我们之前所用的 time 命令是 Bash 的内置命令,功能比较弱;而更强大的 time 命令隐藏在/usr/bin/ 目录下,这个命令才是世外高人。

  • 如果我们在/user/bin/中并没有找到传说中那个强大的 time 命令,那么应该是没有安装 time 这个工具,安装方法也很简单: yum install time

  • 安装完成后,我们就一起来见识 time 命令的庐山真面目吧!我们特意在 time 命令前加了一个斜线\,就是为了调用那个强大的 time 命令,而非 Bash 内置的 time 命令。

[root@xz-qklxi-gs-06 sh]# \time ls
202204151744  a  io  io.sh  psinfo  ps.sh  test.txt
0.00user 0.00system 0:00.00elapsed 50%CPU (0avgtext+0avgdata 964maxresident)k
0inputs+0outputs (0major+292minor)pagefaults 0swaps
[root@xz-qklxi-gs-06 sh]# 
  • 请注意输出内容中的最后两行,打印了很多指标数据,但似乎有点晦涩难懂。这时我们可以使用一个-v选项,这样可以打印出更详细的信息。
# 如果不加\是下面这样的
[root@xz-qklxi-gs-06 sh]# time -v ls
-bash: -v: command not found

real    0m0.002s
user    0m0.000s
sys     0m0.002s
[root@xz-qklxi-gs-06 sh]# 
# 加了\才得行哈
[root@xz-qklxi-gs-06 sh]# \time -v ls
202204151744  a  io  io.sh  psinfo  ps.sh  test.txt
        Command being timed: "ls"
        User time (seconds): 0.00
        System time (seconds): 0.00
        Percent of CPU this job got: 100%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 964
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 294
        Voluntary context switches: 1
        Involuntary context switches: 1
        Swaps: 0
        File system inputs: 0
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
[root@xz-qklxi-gs-06 sh]# 
  • 注意,上面的 Elapsed(wall clock)time(h:mm:ss or m:ss):0:00.00,值是 0,难道执行 ls 命令没有消耗时间?
    非也,事情的真相是这样的:在 time 命令的输出中,Elapsed time 是通过系统调用 gettimeofday 获取到的结束时间和起始时间相减得到的。因此,time 对于运行时间较短的任务计时时,会产生一定误差。time 命令输出的时间统计精度基本在 10 毫秒级。
    原来是精度的问题啊,少于 10 毫秒的程序,真的是连 time 也无法精确计时。

  • Linux time命令提供命令和程序使用情况统计信息,尤其是CPU负载。 时间命令将实际命令作为如下参数获取。
    time 指令可以显示的资源有四大项,分别是:

    • Time taken in user mode
      用户模式下花费的时间
    • Memory usage
      内存使用情况
    • Time taken in kernel mode
      内核模式下花费的时间
    • Time taken in real mode
      实模式下花费的时间

Time resources

Command info

  • time 命令可以显示的资源共有三大项,分别是:时间、内存和 I/O。
    下面来具体看看 time 命令都显示了哪些指标数据。

ime taken in user mode【时间】

  • 指标 含义
    -Command being timed: 执行命令或语句
    • User time 命令执行时在使用者模式所花费的时间,单位是秒
    • System time 命令执行时在内核模式所花费的时间,单位是秒
    • Percent of CPU this job got 命令执行时 CPU 的占用比例。
      其实这个数字就是内核模式的 CPU 时间加上使用者模式的 CPU 时间除以总时间
    • Elapsed (wall clock) time 执行命令所花费的时间,格式是:[hour]:minute:second

Memory resources【内存】

  • 指标 含义
    • Average shared text size 执行程序间共享内容(shared text)的平均值,单位是 KB
    • Average unshared data size 执行程序所占用的私有数据区(unshared data area)的平均 大小,单位是 KB
    • Average stack size 执行程序所占用的私有堆栈(unshared stack)的平均大小, 单位是 KB
    • Average total size 执行程序所占用的内存总量(stack+data+text)的平均大小, 单位是 KB
    • Maximum resident set size 执行程序所占用内存的最大值。单位是 KB
    • Average resident set size 执行程序所占用内存的平均值,单位是 KB

IO resources【I/O】

  • 指标 含义
    • Major (requiring I/O) page faults 此程序的主要内存页错误发生的次数。
      所谓的主要内存页错误是指某一内存页己经詈换到 SWAP 分区中,又被其他程序使用过,该页的内容必须从 SWAP 分区里再读出来才能使用

    • Minor (reclaiming a frame) page faults 此程序的次要内存页错误发生的次数。
      所谓的次要内存页错误是指某一内存页虽然己经詈换到 SWAP 中,但尚未被其他程序使用。此时该页的内容并未 被破坏,不必从 SWAP 分区里读出来即可直接使用

    • Voluntary context switches 此程序自愿中断(I/O 执行完毕,磁碟读取完成等)的次数

    • Involuntary context switches 此程序被强迫中断(如 CPU 时间耗尽)的次数

    • Swaps 此程序被交换到 SWAP 分区的次数

    • File system inputs 此程序所输入的文件数

    • File system outputs 此程序所输出的文件数

    • Socket messages sent 此程序所送出的 Socket Message

    • Socket messages received 此程序所收到的 Socket Message

    • Signals delivered 此程序所收到的信号数

    • Page size 系统内存页的大小,单位是 byte。对于同一个系统来说,这 是个常数

    • Exit status 命令退出状态
      【退出状态说明】
      如果能执行command命令,则返回该命令的退出状态,否则返回如下的退出状态值:
      127 命令未找到
      126 命令找到,但不能执行
      1-125 其它错误

脚本监控记录硬盘io值

[root@xz-qklxi-gs-06 sh]# ls
202204151744  a  io  io.sh  psinfo  ps.sh
[root@xz-qklxi-gs-06 sh]# cat io.sh 
#!/bin/bash

date >> /sh/io/`date +%Y%m%d`
echo "vmstst" >> /sh/io/`date +%Y%m%d`
vmstat 2 5 >> /sh/io/`date +%Y%m%d`
echo "iostat" >> /sh/io/`date +%Y%m%d`
iostat -dx 2 3 >> /sh/io/`date +%Y%m%d`
echo "___________________________________" >> /sh/io/`date +%Y%m%d`
echo -e "\n" >> /sh/io/`date +%Y%m%d`
[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# cat ps.sh 
#!/bin/bash

date >> /sh/psinfo/`date +%Y%m%d`
for x in `seq 1 1 10`;do ps -eo state,pid,cmd | grep "^D" ;echo "__________";sleep 1;done >>  /sh/psinfo/`date +%Y%m%d`
echo -e "\n" >> /sh/io/`date +%Y%m%d`
[root@xz-qklxi-gs-06 sh]# 
  • 然后把这些脚本放到定时任务中,每分钟执行一次
[root@xz-qklxi-gs-06 sh]# crontab -l
* * * * * sh /sh/io.sh
* * * * * sh /sh/ps.sh
[root@xz-qklxi-gs-06 sh]# 
  • 关注反馈结果
    因为我这几天前就已经记录上了,所以我丢部分结果出来把。
[root@xz-qklxi-gs-06 sh]# ls
202204151744  a  io  io.sh  psinfo  ps.sh
[root@xz-qklxi-gs-06 sh]# ls io
20220415  20220416  20220417  20220418  20220419
[root@xz-qklxi-gs-06 sh]# cat io/20220419 | tail -n 20
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 14390240   2088 1228032    0    0     1     9   27   20  0  0 100  0  0
 0  0      0 14390768   2088 1228116    0    0     0     0  296  234  0  0 100  0  0
 0  0      0 14390780   2088 1228116    0    0     0   328  278  160  0  0 100  0  0
 0  0      0 14390672   2088 1228212    0    0     0     0  307  201  0  0 100  0  0
 0  0      0 14390464   2088 1228208    0    0     0     0  275  179  0  0 100  0  0
iostat
Linux 3.10.0-693.el7.x86_64 (xz-qklxi-gs-06.novalocal)  04/19/2022      _x86_64_        (8 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.48    0.09    9.21     6.42    68.86    16.19     3.88  416.70   54.53  420.14  24.28  22.58
vdb               0.00     0.00    0.00    0.00     0.03     0.00    47.27     0.00    0.77    0.77    0.00   0.52   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     8.00     0.00    1.33    1.33    0.00   1.33   0.00

___________________________________




[root@xz-qklxi-gs-06 sh]# 
[root@xz-qklxi-gs-06 sh]# ls psinfo/
20220415  20220416  20220417  20220418  20220419
[root@xz-qklxi-gs-06 sh]# tail -n20 psinfo/20220419
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
__________
[root@xz-qklxi-gs-06 sh]# 

定位linux系统中await值过高占用的盘

  • 要用到iostat命令,需要先安装下面这个包
    yum install sysstat -y

  • iowait实际测量的是cpu时间:
    %iowait = (cpu idle time)/(all cpu time)
    说明:高速cpu会造成很高的iowait值,但这并不代表磁盘是系统的瓶颈。唯一能说明磁盘是系统瓶颈的方法,就是很高的read/write时间,一般来说超过20ms,就代表了不太正常的磁盘性能。为什么是20ms呢?一般来说,一次读写就是一次寻到+一次旋转延迟+数据传输的时间。由于,现代硬盘数据传输就是几微秒或者几十微秒的事情,远远小于寻道时间220ms和旋转延迟48ms,所以只计算这两个时间就差不多了,也就是15~20ms。只要大于20ms,就必须考虑是否交给磁盘读写的次数太多,导致磁盘性能降低了。

开始定位硬盘IO性能

  • I/O问题一直是一个比较难定位的问题,今天线上环境遇到了I/O 引起的CPU负载问题,尝试解决一下。
    • Linux 有许多可用来查找问题的简单工具,也有许多是更高级的
    • I/O Wait 就是一个需要使用高级的工具来debug的问题,当然也有许多基本工具的高级用法。
    • I/O wait的问题难以定位的原因是因为我们有很多工具可以告诉你说I/O 受限了,但是并没有告诉你具体是那个进程引起的(哪些进程们)。
  • 定位io性能,常用的有2种方式
    • 1、 直接用top
    • 2、用iostat命令

top命令

  • 其实top主要是确认是否是I/O问题导致系统缓慢
    确认是否是I/O导致的系统缓慢我们可以使用多个命令,但是,最简单的是unix的命令 top
  • 直接在系统中执行top命令即可
    如下,第三行【Cpu一行wa值 = iowait】wa值我们可以看到浪费在I/O Wait上的CPU百分比;这个数字越高说明越多的CPU资源在等待I/O权限。
[root@xz-qklxi-gs-06 ~]# top
top - 01:52:32 up 1 day, 15:28,  1 user,  load average: 0.11, 0.10, 0.12
Tasks: 143 total,   1 running, 142 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.6 us,  1.4 sy,  0.0 ni, 95.3 id,  2.6 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16267172 total, 14257480 free,   654824 used,  1354868 buff/cache
KiB Swap:        0 total,        0 free,        0 used. 15223900 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                              
 5399 root      20   0  145700   5204   3940 S   4.7  0.0   0:00.14 sshd                                                                 
 2601 root      20   0       0      0      0 S   1.0  0.0   0:02.08 kworker/0:0                                                          
    1 root      20   0   54564   6916   4056 S   0.7  0.0   2:07.20 systemd                                                              
 5404 xz_tyng   20   0  113300   1724   1328 S   0.7  0.0   0:00.02 bash                                                                 
  603 dbus      20   0   32692   1832   1380 S   0.3  0.0   0:52.02 dbus-daemon                                                          
  615 root      20   0   24204   1720   1396 S   0.3  0.0   0:30.44 systemd-logind                                                       
18056 root      20   0 1028424  46780  16448 S   0.3  0.3   0:20.42 containerd                                                           
18832 root      20   0  111956  12152   3920 S   0.3  0.1   0:34.99 containerd-shim                                                      
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.31 kthreadd                                                             
    3 root      20   0       0      0      0 S   0.0  0.0   0:00.07 ksoftirqd/0                
  • 上边的top命令从一个整体上说明了I/O wait,但是并没有说明是哪块磁盘影响的,想知道是哪块磁盘引发的问题,我们要用到另外一个命令 iostat 命令

iostat命令

  • 这个能查找哪块磁盘正在被写入。【我这情况比较特殊,top看到wa等待并不高,但是iostat看到的值很高,所以主要用这个命令来定位】
  • 我之前的文章中已经对iostat这个命令做过详细说明,我这不再说明,对iostat有疑问的可以去下面这篇文章中看看
    监控不同外挂盘的硬盘io、查看linux命令运行时间和记录、iostat命令查看硬盘io、查看硬盘io的几种方法、定位到硬盘io高的dm
    我这丢张截图,方便理解。
    在这里插入图片描述
  • 在系统直接执行iostat -dx 2 5
    • -d 仅显示磁盘统计信息.与-c选项互斥, -x 的选项是打印出扩展信息 ,iostat 会每2秒更新一次,一共打印5次信息,
    • 第一个iostat 报告会打印出系统最后一次启动后的统计信息,这也就是说,在多数情况下,第一个打印出来的信息应该被忽略,剩下的报告,都是基于上一次间隔的时间。
    • 举例子来说,这个命令会打印5次,第二次的报告是从第一次报告出来一个后的统计信息,第三次是基于第二次 ,依次类推。【所以我下面io高并不是一直持续的,如下,第一次和第四次io才高,是偶发性的,也就导致vi保存缓慢会频繁发生。。。】
      如下执行结果中,sda的%utilized 是24%,这个很好的说明了有进程正在写入到sda磁盘中。
    • 除了%utilized 外,我们可以得到更丰富的资源从iostat,例如每秒读写请求(rrqm/s & wrqm/s),每秒读写的(r/s & w/s),当然还有更多。在下面的例子中,我们的项目看起来正在读写非常多的信息。这个对我们查找相应的进程非常有用。
[root@xz-qklxi-gs-06 ~]# iostat -x 2 5
Linux 3.10.0-693.el7.x86_64 (xz-qklxi-gs-06.novalocal)  04/20/2022      _x86_64_        (8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.12    0.00    0.14    0.10    0.00   99.64

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.46    0.05   10.70     3.69    74.04    14.45     4.55  422.99   54.10  424.85  22.44  24.13
vdb               0.00     0.00    0.00    0.00     0.01     0.00    47.27     0.00    0.77    0.77    0.00   0.52   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     8.00     0.00    1.33    1.33    0.00   1.33   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.06    0.00    0.00    0.00    0.00   99.94

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.06    0.00    0.12    0.00    0.00   99.81

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.12    0.00    0.00    0.00    0.00   99.88

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     2.50    0.00   61.00     0.00   348.75    11.43    20.57  337.28    0.00  337.28  12.10  73.80
vdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.13    0.00    0.06    0.00    0.00   99.81

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

[root@xz-qklxi-gs-06 ~]# 

查找引起高I/O wait 对应的进程pid

iotop定位

  • 最简单的方式是使用命令iotop,通过查看iotop的统计信息,我们就可以很直观的看到是啥程序在占用io了。
    这个命令系统应该不会自带,需要安装:yum -y install iotop

  • 用法:iotop [OPTIONS]

  • 选项:

    • –version #显示版本号
    • -h, --help #显示帮助信息
    • -o, --only #显示进程或者线程实际上正在做的I/O,而不是全部的,可以随时切换按o
    • -b, --batch #运行在非交互式的模式
    • -n NUM, --iter=NUM #在非交互式模式下,设置显示的次数,
    • -d SEC, --delay=SEC #设置显示的间隔秒数,支持非整数值
    • -p PID, --pid=PID #只显示指定PID的信息
    • -u USER, --user=USER #显示指定的用户的进程的信息
    • -P, --processes #只显示进程,一般为显示所有的线程
    • -a, --accumulated #显示从iotop启动后每个线程完成了的IO总数
    • -k, --kilobytes #以千字节显示
    • -t, --time #在每一行前添加一个当前的时间
    • -q, --quiet #suppress some lines of header (implies --batch). This option can be specified up to three times to remove header lines.
    • -q column names are only printed on the first iteration,
    • -qq column names are never printed,
    • -qqq the I/O summary is never printed.
  • 可用的命令(在运行iotop命令后按相应键位):
    使用left和right改变排序(方向键改变排序列),还可使用以下命令:

    • r:反向排序,
    • o:切换至选项–only,
    • p:切换至–processes选项,
    • a:切换至–accumulated选项
    • q:退出
    • i:改变线程的优先级
      例子:
#默认使用
 iotop
 
# 常用:只显示有I/O行为的进程
  iotop -oP
  
# 加其他参数
 iotop –b –n 3 –d 5

  • 好了,上面说完了iotop的使用,开始回到正轨了
    我们直接执行iotop即可
    好像看着啥都不高,一切岁月静好的样子。。。这个方法好像有点不太适合我哈。
[root@xz-qklxi-gs-06 ~]# iotop   
 2601 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.06 % [kworker/0:0]
Total DISK READ :       0.00 B/s | Total DISK WRITE :     376.93 K/s
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       0.00 B/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                   
18267 be/4 root        0.00 B/s    3.89 K/s  0.00 %  0.00 % dockerd -H fd:// --containerd=/run/containerd/containerd.sock
18854 be/4 root        0.00 B/s  373.04 K/s  0.00 %  0.00 % nodeos --genesis-json /etc/eos/genesis~dir /var/lib/eos --verbose-http-errors
    1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % systemd --switched-root --system --deserialize 19
    2 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]
    3 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [ksoftirqd/0]
    5 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kworker/0:0H]
    6 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kworker/u16:0]
  • 所以我们换下面种方法查看

ps定位

  • 这个呢属于进程的状态来定位了
  • ps 命令对内存和CPU有一个统计,但是他没有对磁盘I/O的统计,虽然他没有显示磁盘I/O,但是它显示进行的状态,我们可以用来知道一个进程是否正在等待I/O
    ps state状态来表示了process现在的状态,下面是各个状态的帮助文档
    • D不间断睡眠(通常是IO)
    • R r正在运行或可运行(在运行队列中)
    • S 可中断睡眠(等待事件完成)
    • T由于作业控制信号或被跟踪而停止
    • W 分页(从2.6.xx内核开始无效)
    • X 死了(永远不会被看到)
    • Z已失效(“僵尸”)进程,已终止但未被其父进程获取。
  • 而那些等待I/O的进程的状态一般是“uninterruptible sleep【不间断睡眠】”,也就是上面D,我们可以很容易的查找到正在等待I/O的进程
    这个呢是需要一个语句来查看的
    下面语句呢,你执行可能不会有结果,全是----,我是放到脚本里一直监控,所以才有值的。
[root@xz-qklxi-gs-06 sh]# for x in `seq 1 1 10`;do ps -eo state,pid,cmd | grep "^D" ;echo "__________";sleep 1;done 
__________
__________
Wed Apr 20 02:51:01 UTC 2022
__________
__________
__________
__________
D   336 [xfsaild/vda1]
__________
D   336 [xfsaild/vda1]
  • 上边的例子会循环的输出状态是D的进程,每5秒一次,一共10次
    但我现在不确定是不是我监控到的pid为336的程序。

  • 因为网上的说法是这种
    在这里插入图片描述

  • 因为这样并不能证明这就是IO灯带的直接原因,所以我们接着往下看。

查找是那个文件引起的I/Owait

/proc/pid/文件查看

  • 这是一个强大的文件
    Proc 是一个虚拟文件系统,在Linux 系统中它被挂载于/proc 目录之上。Proc 有多个功能 ,这其中包括用户可以通过它访问内核信息或用于排错,这其中一个非常有 用的功能,也是Linux 变得更加特别的功能就是以文本流的形式来访问进程信息。很Linux 命令( 比如 ps 、toPpstree 等) 都需要使用这个文件系统的信息。注意, 本文就是向用户介绍一些访问这些信息的方法 。需要说明的是,本文所述的内容并不 一定适用所有内核版本,有部分操作只适用于2.6 内核。
  • 所有进程信息
    在/proc 文件系统中,每一个进程都有一个相应的文件 。下面是/proc 目录下的一些重要文件 :
    /proc/pid/cmdline 包含了用于开始进程的命令 ;
    /proc/pid/cwd 包含了当前进程工作目录的一个链接 ;
    /proc/pid/environ 包含了可用进程环境变量的列表 ;
    /proc/pid/exe 包含了正在进程中运行的程序链接;
    /proc/pid/fd/ 这个目录包含了进程打开的每一个文件的链接;
    /proc/pid/mem 包含了进程在内存中的内容;
    /proc/pid/stat 包含了进程的状态信息;
    /proc/pid/statm 包含了进程的内存使用信息。
    /proc/pid/io 包含硬盘IO信息。
    上面详细的呢去看这篇大佬的文章:`linux proc/pid/信息说明
  • 我们定位io呢可以使用 /proc/pid文件系统,每个进程目录下都有一个叫io的文件,里边保存这和iotop类似的信息
    命令是:cat /proc/pidnum/io【pid是通过上面定位到的,或者你想查看的任何pid数值】
    如下
[root@xz-qklxi-gs-06 psinfo]# cat /proc/336/io
rchar: 0
wchar: 0
syscr: 0
syscw: 0
read_bytes: 98304
write_bytes: 0
cancelled_write_bytes: 0
[root@xz-qklxi-gs-06 psinfo]# 
  • 参数说明【内容来源于国外英文网站的网页翻译哈】
rchar
-----
I/O counter: chars read
The number of bytes which this task has caused to be read from storage. This
is simply the sum of bytes which this process passed to read() and pread().
It includes things like tty IO and it is unaffected by whether or not actual
physical disk IO was required (the read might have been satisfied from
pagecache)
此任务导致从存储中读取的字节数。这 就是这个进程传递给read()和pread()的字节数的总和。 
它包括tty IO之类的东西,不受实际与否的影响 需要物理磁盘IO(读取可能已经从 页面缓存)

wchar
-----
I/O counter: chars written
The number of bytes which this task has caused, or shall cause to be written
to disk. Similar caveats apply here as with rchar.
该任务已经导致或将要导致写入的字节数 到磁盘。类似的警告也适用于rchar。

read_bytes
----------
I/O counter: bytes read
Attempt to count the number of bytes which this process really did cause to
be fetched from the storage layer. Done at the submit_bio() level, so it is
accurate for block-backed filesystems. <please add status regarding NFS and
CIFS at a later time>
尝试计算该进程确实导致的字节数 从存储层获取。在submit_bio()级别完成,确实如此 对于数据块支持的文件系统是准确的。

write_bytes
-----------
I/O counter: bytes written
Attempt to count the number of bytes which this process caused to be sent to
the storage layer. This is done at page-dirtying time.
尝试计算该进程导致发送到的字节数 存储层。这是在弄脏页面的时候完成的。

#另外还有3个参数官网没说明
syscr —— 系统读的字节 【我猜的,网上找不到这个信息的说明】
syscw —— 系统写的字节 【我猜的,网上找不到这个信息的说明】
cancelled_write_bytes —— 已取消写入字节【直接翻译的】
  • 理论上我上面的这个io很低,并不会对vi保存产生影响才对,可vi保存缓慢始终存在,就很离谱哦。
    因为网上的这个io值是这样的
    在这里插入图片描述

lsof命令的使用和查看

  • lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以,lsof的功能很强大。一般root用户才能执行lsof命令,普通用户可以看见/usr/sbin/lsof命令,但是普通用户执行会显示“permission denied”。因此通过lsof工具能够查看这个列表对系统监测以及排错将是很有帮助的。

  • lsof 命令可以展示一个进程打开的所有文件,或者打开一个文件的所有进程。从这个列表中,我们可以找到具体是什么文件被写入,根据文件的大小和/proc中io文件的具体数据。
    这个命令需要安装的:yum -y install lsof

  • lsofl各列头说明
    在这里插入图片描述
    每行显示一个打开的文件,若不指定条件默认将显示所有进程打开的所有文件。lsof输出各列信息的意义如下:

    • COMMAND:进程的名称
    • PID:进程标识符
    • USER:进程所有者
    • FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等
    • TYPE:文件类型,如DIR、REG等
    • DEVICE:指定磁盘的名称
    • SIZE/OFF:文件的大小
    • NODE:索引节点(文件在磁盘上的标识)
    • NAME:打开文件的确切名称
  • lsof指令的更多用法如下【我随便弄几个截图展示使用方法把】:
    -lsof abc.txt显示开启文件abc.txt的进程 【我好像可以通过这个定位到pid,直接kill杀死欸】
    在这里插入图片描述
    -lsof 目录名 查找谁在使用文件目录系统
    在这里插入图片描述
    -lsof -i :22 知道22端口被哪个进程占用
    在这里插入图片描述
    -lsof -c abc 显示abc进程现在打开的文件
    -lsof -g gid 显示归属gid的进程情况
    -lsof -n 不将IP转换为hostname,缺省是不加上-n参数
    -lsof -p 12 看进程号为12的进程打开了哪些文件
    -lsof -u username 查看用户打开哪些文件
    -lsof -i @192.168.1.111 查看远程已打开的网络连接(连接到192.168.1.111)

  • 特殊用法,见下面。

lsof -i 用以显示符合条件的进程情况

语法: lsof -i[46] [protocol][@hostname|hostaddr][:service|port]

46 -> IPv4 or IPv6

protocol -> TCP or UDP

hostname -> Internet host name

hostaddr -> IPv4位置

service -> /etc/service中的 service name (可以不只一个)

port -> 端口号 (可以不只一个)

--------------------------------------
lsof +|-r [t] 控制lsof不断重复执行,缺省是15s刷新

-r,lsof会永远不断的执行,直到收到中断信号

+r,lsof会一直执行,直到没有档案被显示

例子:不断查看目前ftp连接的情况:lsof -i [email protected]:ftp -r
  • 好了,上面说完lsof的用法,开始回到正轨了
    我们前面定位出了进程高的pid,所以我们直接通过lsof -p pid定位即可
    我上面通过ps过滤到的pid是336,所以如下
[root@xz-qklxi-gs-06 ~]# lsof -p 336
COMMAND   PID USER   FD      TYPE DEVICE SIZE/OFF NODE NAME
xfsaild/v 336 root  cwd       DIR  253,1      272   64 /
xfsaild/v 336 root  rtd       DIR  253,1      272   64 /
xfsaild/v 336 root  txt   unknown                      /proc/336/exe
[root@xz-qklxi-gs-06 ~]# 
  • 然后直接df -h 上面的NAME路径,就可以看到是哪个盘io高了
    如,我上面的是/目录,所以我直接df -h /
[root@xz-qklxi-gs-06 ~]# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G  7.1G   43G  15% /
[root@xz-qklxi-gs-06 ~]# 
  • 如果你的系统有化lv,则继续执行pvs或者pvdisplay查看上面获取到的Filesystem的详细磁盘信息,从而更精确的定位是哪个分区。
    我这系统没化lv,所以也就没装这些命令。
[root@xz-qklxi-gs-06 ~]# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G  7.1G   43G  15% /
[root@xz-qklxi-gs-06 ~]# 
- [root@xz-qklxi-gs-06 ~]# pvs
-bash: pvs: command not found
[root@xz-qklxi-gs-06 ~]# 
[root@xz-qklxi-gs-06 ~]# pvdisplay
-bash: pvdisplay: command not found
[root@xz-qklxi-gs-06 ~]# 

[root@xz-qklxi-gs-06 ~]# lsof -p 336
COMMAND   PID USER   FD      TYPE DEVICE SIZE/OFF NODE NAME
xfsaild/v 336 root  cwd       DIR  253,1      272   64 /
xfsaild/v 336 root  rtd       DIR  253,1      272   64 /
xfsaild/v 336 root  txt   unknown                      /proc/336/exe
[root@xz-qklxi-gs-06 ~]# 
[root@xz-qklxi-gs-06 ~]# ps -ef | grep 336
root       336     2  0 Apr18 ?        00:00:57 [xfsaild/vda1]
root     28657 25203  0 03:41 pts/1    00:00:00 grep --color=auto 336
[root@xz-qklxi-gs-06 ~]# 
[root@xz-qklxi-gs-06 ~]# kill -d 336
-bash: kill: d: invalid signal specification
[root@xz-qklxi-gs-06 ~]# kill -9 336
[root@xz-qklxi-gs-06 ~]# ps -ef | grep 336
root       336     2  0 Apr18 ?        00:00:57 [xfsaild/vda1]
root     29139 25203  0 03:44 pts/1    00:00:00 grep --color=auto 336
[root@xz-qklxi-gs-06 ~]# kill -9 336
[root@xz-qklxi-gs-06 ~]# 
[root@xz-qklxi-gs-06 ~]# ps -ef | grep 336
root       336     2  0 Apr18 ?        00:00:57 [xfsaild/vda1]
root     29150 25203  0 03:44 pts/1    00:00:00 grep --color=auto 336
[root@xz-qklxi-gs-06 ~]# 
[root@xz-qklxi-gs-06 ~]# iostat -dx 2 3
Linux 3.10.0-693.el7.x86_64 (xz-qklxi-gs-06.novalocal)  04/20/2022      _x86_64_        (8 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.45    0.05   10.80     3.56    74.48    14.38     4.55  418.81   54.18  420.57  22.25  24.15
vdb               0.00     0.00    0.00    0.00     0.01     0.00    47.27     0.00    0.77    0.77    0.00   0.52   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     8.00     0.00    1.33    1.33    0.00   1.33   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     1.50    0.00   41.00     0.00   264.00    12.88     5.30  129.23    0.00  129.23   3.30  13.55
vdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
scd0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

[root@xz-qklxi-gs-06 ~]# 

总结

  • 综上,我还是没能定位到vi保存慢的原因,甚至连释放iostat中的await的值都做不到,找了其他大佬也没能搞定,我现在技术沉淀不够,先记录把,以后学更多知识了,在返回来整理这个问题。

  • 而且释放await值确实不是很简单的一件事,牵扯的东西太多了,对存储了解不够,不知道原理,可能做不到这个。

  • 我这遇到的情况,硬盘io其实是蛮正常的,里面也没啥大程序,初步认定为:
    await大于svctm,它们的差值越小,则说明队列时间越短,反之差值越大,队列时间越长,说明系统出了问题。
    再排查也还有几个方向:

    • 可以考虑更换更快的磁盘
    • 调整内核 elevator 算法
    • 优化应用
    • 或者升级 CPU【队列长度(avgqu-sz)也可作为衡量系统 I/O 负荷的指标】
    • 最直接的方法:重装。
  • ps:网上很多解决iostat中await值过高的文章,全是标题党,没一个是能解决的,都是定位到磁盘,而且基本上都是复制粘贴的内容,这种百度出千律一篇的文章真是浪费时间。

猜你喜欢

转载自blog.csdn.net/cuichongxin/article/details/124277983
今日推荐