测试工作常用Linux shell命令-top与ps命令统计某进程CPU、MEM以及grep --line-buffered的应用

1,344 阅读4分钟

先来看ps命令,通过ps -aux 可以查看到进程的CPU和MEM等信息:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3 191808  3764 ?        Ss    2018   2:44 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
root         2  0.0  0.0      0     0 ?        S     2018   0:02 [kthreadd]
root         3  0.0  0.0      0     0 ?        S     2018   5:23 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S<    2018   0:00 [kworker/0:0H]
root         7  0.0  0.0      0     0 ?        S     2018   0:00 [migration/0]
root     22056  0.1  2.0 750304 20340 ?        Ssl  9月07   3:07 /usr/local/cloudmonitor/CmsGoAgent.linux-amd64
......#后面内容省略

这里我们单独取PID为22056的CmsGoAgent进程的CPU和MEM信息 命令:ps -o %cpu %,mem -p 22056

[16210504@izuf60jasqavbxb9efockpz ~]$ ps -o %cpu,%mem -p 22056
%CPU %MEM
 0.1  2.0

由上面的结果可以看到成功拿出了结果,但是这个结果其实是不准确的,使用man ps命令,查看ps统计信息的说明如下:

%cpu        %CPU      cpu utilization of the process in "##.#" format.  Currently, it is the CPU time used divided by the time the process has been running (cputime/realtime ratio), expressed as a percentage.  It will not add up to 100% unless you are lucky.
                             (alias pcpu).

%mem        %MEM      ratio of the process's resident set size  to the physical memory on the machine, expressed as a percentage.  (alias pmem).

我们可以看到ps命令统计CPU的信息是拿CPU使用的时间除以进行总运行的时间(cputime/realtime ratio),这样就有可能出现,CPU在某个时间里利用率很高,但是因为进程已经运行了很久了,导致实际算出来的值依然是很小的,影响结果的判断,通常我们关注的是CPU在连续的变化情况,也就是需要CPU的切片信息; 这个时候我们想要即使的统计信息就需要使用top命令了:

[16210504@izuf60jasqavbxb9efockpz ~]$ top
top - 23:03:54 up 316 days, 13:52, 13 users,  load average: 0.00, 0.01, 0.05
Tasks: 159 total,   1 running, 113 sleeping,  45 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.7 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1016396 total,   434728 free,   133020 used,   448648 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   710848 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
22056 root      20   0  750304  20472   5612 S  0.3  2.0   3:23.00 CmsGoAgent.linu
    1 root      20   0  191808   3764   1436 S  0.0  0.4   2:44.29 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:02.10 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   5:23.84 ksoftirqd/0
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    7 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
    9 root      20   0       0      0      0 S  0.0  0.0  42:39.12 rcu_sched

先过滤出PID为22056的CmsGoAgent进程的CPU和MEM信息 命令:top -b -p 22056 -d 1

-b : 批处理模式,可以把输出导给下一个进程
-p : 打印某一个进程
-d 1 : 每隔1秒打印一次 
[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -d 1
top - 23:14:52 up 316 days, 14:03, 10 users,  load average: 0.00, 0.01, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.5 us,  2.5 sy,  0.0 ni, 94.9 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1016396 total,   444484 free,   122968 used,   448944 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   721340 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
22056 root      20   0  750304  20472   5612 S  0.0  2.0   3:24.04 CmsGoAgent.linu

top - 23:14:53 up 316 days, 14:03, 10 users,  load average: 0.00, 0.01, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1016396 total,   444484 free,   122968 used,   448944 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   721340 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
22056 root      20   0  750304  20472   5612 S  0.0  2.0   3:24.04 CmsGoAgent.linu
......#后面的内容省略

#不用-b命令的效果(进入交互模式):
16210504@izuf60jasqavbxb9efockpz ~]$ top  -p 22056 -d 1
top - 23:18:05 up 316 days, 14:07, 10 users,  load average: 0.13, 0.04, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.0 us,  0.0 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1016396 total,   444360 free,   123004 used,   449032 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   721304 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
22056 root      20   0  750304  20472   5612 S  0.0  2.0   3:24.37 CmsGoAgent.linu

...#中间不会输出任何内容...

[16210504@izuf60jasqavbxb9efockpz ~]$
  • 现在利用top命令来完成性能数据CPU、MEM信息的需求:

需求:统计进程10次的CPU和MEM的变化情况并输出平均值 预计效果:

CPU  MEM
0.1  2.0
0.1  2.1
...#共统计10次
-----
0.13 2.4  #这里是平均值

实现: 每隔1秒打印一次进程信息,共打印10次,过滤出只包含进程信息的行: 命令:top -b -p 22056 -n 10 -d 1 | grep 22056

[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -n 10 -d 1 | grep 22056
22056 root      20   0  750304  20476   5616 S  0.0  2.0   3:26.70 CmsGoAgent.linu
22056 root      20   0  750304  20476   5616 S  0.0  2.0   3:26.70 CmsGoAgent.linu
22056 root      20   0  750304  20476   5616 S  0.0  2.0   3:26.70 CmsGoAgent.linu
......#共打印出10行

利用awk命令分别取出第9,第10段信息,对应着CPU和MEM,并用BEGAIN命令先打印出头信息 命令:top -b -p 22056 -n 10 -d 1 | grep 22056 | awk BEGAIN{print "CPU%","MEM%"}

[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -n 10 -d 1 | grep 22056 | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}'
CPU% MEM%



现在出现了一个现象,awk切片后的信息没有被实时打印出来,在大概过了10秒后,所有的信息被一起打印出来如下:

[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -n 10 -d 1 | grep 22056 | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}'
CPU% MEM%
#10秒后所有信息被一起打印
0.0 2.0
1.0 2.0
1.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0

这里要先引出另一个问题:grepawk处于效率的考量,会缓存一批数据再输出到标准输出,就会导致即使满足匹配条件也不会即使打印出来,想要获取即时的信息,就需要使用grep --line-buffered,使grep不缓存信息,直接输出: 另外,由于最后还要算平均值,所以每次的数据都需要存在一个变量中 命令:top -b -p 22056 -n 10 -d 1 | grep 22056 --line-buffered | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}{cpu+=$9;mem+=$10}'

[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -n 10 -d 1 | grep 22056 --line-buffered | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}{cpu+=$9;mem+=$10}'
CPU% MEM%
0.0 2.0
0.0 2.0
0.0 2.0
1.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0

最后,我们我们利用awkEND,来输出分隔符,并计算最终的平均值打印出来(其中的NR表示总行数) 命令:top -b -p 22056 -n 10 -d 1 | grep 22056 --line-buffered | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}{cpu+=$9;mem+=$10}END{print "------";print cpu/NR,mem/NR}' 最终结果:

[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -n 10 -d 1 | grep 22056 --line-buffered | awk 'BEGIN{print "CPU%","MEM%"}{print $9,$10}{cpu+=$9;mem+=$10}END{print "------";print cpu/NR,mem/NR}'
CPU% MEM%
0.0 2.0
0.0 2.0
0.0 2.0
1.0 2.0
0.0 2.0
0.0 2.0
0.0 2.0
1.0 2.0
0.0 2.0
0.0 2.0
------
0.2 2

也可以即使打印平均值信息,并用OFS指定制表符的方式进行格式化输出: 命令:top -b -p 22056 -n 20 -d 1 | grep --line-buffered 22056 | awk 'BEGIN{OFS="\t";print "cpu","mem","avgc","avgm"}{c+=$9;m+=$10;print $9,$10,c/NR,m/NR}'

[16210504@izuf60jasqavbxb9efockpz ~]$ top -b -p 22056 -n 20 -d 1 | grep --line-buffered 22056 | awk 'BEGIN{OFS="\t";print "cpu","mem","avgc","avgm"}{c+=$9;m+=$10;print $9,$10,c/NR,m/NR}'
cpu	mem	avgc	avgm
0.0	2.0	0	2
0.0	2.0	0	2
0.0	2.0	0	2
0.0	2.0	0	2
0.0	2.0	0	2
0.0	2.0	0	2
0.0	2.0	0	2
0.0	2.0	0	2
2.0	2.0	0.222222	2
0.0	2.0	0.2	2
0.0	2.0	0.181818	2
0.0	2.0	0.166667	2
0.0	2.0	0.153846	2
0.0	2.0	0.142857	2
0.0	2.0	0.133333	2
0.0	2.0	0.125	2
0.0	2.0	0.117647	2
0.0	2.0	0.111111	2
0.0	2.0	0.105263	2
0.0	2.0	0.1	2