计算Linux系统的CPU利用率
通过读取系统的/proc/stat 信息来计算CPU的利用率
cpu 信息的读取
摘自参考博客:https://blog.csdn.net/x_i_y_u_e/article/details/50684508
在Linux/Unix下,CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间 / CPU总的执行时间。
在Linux的内核中,有一个全局变量:Jiffies。 Jiffies代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位就是1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。 CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。
在Linux系统中,可以用/proc/stat文件来计算cpu的利用率(详细的解释可参考:http://www.linuxhowtos.org/System/procstat.htm)。这个文件包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。
在本机上的信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| root@hw103:/home/yky# cat/proc/stat cpu 7283854 35392 293546 204419077 75835 0 8385 0 0 0 cpu0 365010 48 18204 8453603 767 0 4306 0 0 0 cpu1 292817 9 14990 8526563 1358 0 2114 0 0 0 cpu2 286689 0 11880 8538662 1033 0 752 0 0 0 cpu3 287106 14624 12945 8523209 641 0 320 0 0 0 cpu4 293293 0 11784 8532282 604 0 147 0 0 0 cpu5 371312 2824 13669 8408187 40794 0 406 0 0 0 cpu6 358116 10934 14014 8453775 1230 0 68 0 0 0 cpu7 313971 6281 12243 8504303 1575 0 28 0 0 0 cpu8 318084 0 11598 8506770 2036 0 15 0 0 0 cpu9 294503 0 11137 8530318 2185 0 10 0 0 0 cpu10 307922 144 12434 8516570 1177 0 15 0 0 0 cpu11 291752 0 11502 8533957 1128 0 4 0 0 0 cpu12 315096 0 15927 8503001 3528 0 3 0 0 0 cpu13 375976 0 17927 8442873 2041 0 1 0 0 0 cpu14 299344 0 10140 8523716 2818 0 1 0 0 0 cpu15 288470 3 10146 8538685 1240 0 0 0 0 0 cpu16 301148 0 10681 8523612 2185 0 0 0 0 0 cpu17 263183 4 9149 8565345 771 0 0 0 0 0 cpu18 262518 370 10343 8562955 2105 0 11 0 0 0 cpu19 280230 3 10399 8546414 1227 0 6 0 0 0 cpu20 278962 0 10346 8547585 1221 0 9 0 0 0 cpu21 277042 143 11502 8547940 1048 0 2 0 0 0 cpu22 275560 0 9458 8549093 1271 0 153 0 0 0 cpu23 285740 0 11118 8539648 1838 0 6 0 0 0 intr 91288599 43 2 0 0 0 0 0 0 1 0 0 0 4 0 0 0 41 0 2 0 0 0 0 0 0 0 334158 0 1 2473208 45518 96917 44876 138077 45263 45258 54441 0 0 44198 44198 44198 44198 44198 44198 441 98 44198 0 0 44198 44198 44198 44198 44198 44198 44198 44198 0 0 44199 44199 44199 44199 44199 44199 44199 44199 0 0 44199 44199 44199 44199 44199 44199 44199 44199 0 0 44198 44198 44198 44198 44198 44198 44198 44198 0 0 44198 44198 44198 44198 44198 44198 44198 44198 0 0 44199 44199 44199 44199 44199 44199 44199 44199 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0ctxt 42731429 btime 1553933982 processes 190449 procs_running 5 procs_blocked 0 softirq 57291816 8 26401645 17536 5419485 334063 0 1044 10019160 0 15098875
|
第一行cpu是总的cpu信息,其他的cpu0-cpu23 是24个核的信息。
计算cpu利用率只用到前7个参数, 对应的参数解释为:
1 2
| user nice system idle iowait irq softirq cpu 7283854 35392 293546 204419077 75835 0 8385
|
user (7283854) 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒
nice (35392) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
system (293546) 从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
idle (204419077) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
iowait (75835) 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
irq (0) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
softirq (8385) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)
CPU时间=user+system+nice+idle+iowait+irq+softirq
“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。
计算cpu利用率的方法就是计算出在一段时间里面,cpu工作的时间/总得时间
1 2
| cpu usage=(idle2-idle1)/(cpu2-cpu1)*100 cpu usage=[(user_2 +sys_2+nice_2) - (user_1 + sys_1+nice_1)]/(total_2 - total_1)*100
|
第二中方法只把user+sys+nice 这三个时间看作cpu的工作时间,因为其他的几个比较小。
shell脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #!/bin/bash
#
cpulog_start=$(cat /proc/stat | grep 'cpu'| awk 'NR==1{print $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8}' ) cpu_use_start=$(echo $cpulog_start | awk '{print $1+$2+$3}') cpu_iowait_start=$(echo $cpulog_start | awk '{print $5}') cpu_total_start=$(echo $cpulog_start | awk '{print $1+$2+$3+$4+$5+$6+$7}')
sleep 10
cpulog_end=$(cat /proc/stat | grep 'cpu'| awk 'NR==1{print $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8}' ) cpu_use_end=$(echo $cpulog_end | awk '{print $1+$2+$3}') cpu_iowait_end=$(echo $cpulog_end | awk '{print $5}') cpu_total_end=$(echo $cpulog_end | awk '{print $1+$2+$3+$4+$5+$6+$7}')
cpu_use_diff=`expr $cpu_use_end - $cpu_use_start` cpu_iowait_diff=`expr $cpu_iowait_end - $cpu_iowait_start` cpu_total_diff=`expr $cpu_total_end - $cpu_total_start`
cpu_use_rate=`expr $cpu_use_diff/$cpu_total_diff*100 | bc -l` cpu_iowait_rate=`expr $cpu_iowait_diff/$cpu_total_diff*100 | bc -l`
echo "---------------cpuinfo----------------------" echo "cpu_usage_rate (%) : $cpu_use_rate" echo "cpu_iowait_rate (%): $cpu_iowait_rate"
|
主要的知识点讲解:
1
| cpulog_start=$(cat /proc/stat | grep 'cpu'| awk 'NR==1{print $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8}' )
|
这一句先将/proc/stat文件的信息读取出来然后用管道| 传递给grep 命令 ,grep 将包含cpu的信息给提取出来
cat /proc/stat | grep 'cpu'
输出为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| root@hw103:/home/yky cpu 7645369 35392 318219 206250476 80895 0 9870 0 0 0 cpu0 365256 48 18792 8544685 767 0 5678 0 0 0 cpu1 292983 9 15427 8618292 1389 0 2206 0 0 0 cpu2 287020 0 12884 8629895 1033 0 760 0 0 0 cpu3 288372 14624 13910 8613386 681 0 320 0 0 0 cpu4 293707 0 13074 8623117 646 0 147 0 0 0 cpu5 390012 2824 15130 8477387 44027 0 418 0 0 0 cpu6 362140 10934 15217 8541127 1233 0 69 0 0 0 cpu7 377620 6281 12915 8532734 1700 0 28 0 0 0 cpu8 333520 0 12524 8582987 2100 0 15 0 0 0 cpu9 348913 0 12619 8567005 2453 0 10 0 0 0 cpu10 333584 144 14002 8581939 1297 0 15 0 0 0 cpu11 292980 0 12966 8623861 1137 0 4 0 0 0 cpu12 350188 0 16793 8559301 4017 0 3 0 0 0 cpu13 430200 0 19278 8479849 2344 0 1 0 0 0 cpu14 312421 0 11483 8601843 2906 0 1 0 0 0 cpu15 343656 3 10768 8575706 1268 0 0 0 0 0 cpu16 302673 0 12190 8613170 2190 0 0 0 0 0 cpu17 263473 4 9906 8656857 771 0 0 0 0 0 cpu18 263094 370 11278 8653940 2165 0 11 0 0 0 cpu19 281216 3 11166 8637253 1280 0 6 0 0 0 cpu20 280412 0 11645 8637433 1221 0 9 0 0 0 cpu21 277219 143 11967 8639929 1048 0 2 0 0 0 cpu22 275894 0 10291 8640508 1271 0 153 0 0 0 cpu23 298806 0 11985 8618261 1939 0 6 0 0 0
|
awk 命令
之后使用awk命令再次进行操作。这个命令之前用的很少,参考《鸟哥的Linux私房菜》介绍:
sed常用于一整行的处理,awk则倾向于将一行分成数个“字段”来处理,awk适合处理小型的数据。
用法为:
awk '条件类型1{操作1} 条件类型1{操作2}...' filename
变量名称 |
意义 |
NF |
每一行($0) 拥有的字段总数 |
NR |
awk当前处理的第几行数据 |
FS |
目前的分割符,默认空格键 |
1
| cpulog_start=$(cat /proc/stat | grep 'cpu'| awk 'NR==1{print $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8}' )
|
NR==1
限定条件为第一行,因为第一行的数据才是cpu的总信息,{}里面的操作是输出字段,$N 就是第N个字段。
1 2 3
| $1 $2 $3 $4 $5 $6 $7 $8 user nice system idle iowait irq softirq cpu 7283854 35392 293546 204419077 75835 0 8385
|
expr
1
| cpu_use_diff=`expr $cpu_use_end - $cpu_use_start`
|
使用expr 执行变量计算,然后是`` 进行反引用将值赋值给cpu_use_diff
注意shell 脚本中= 不能用空格分开 需要直接相邻
bc 命令
bc 命令是任意精度计算器语言,通常在linux下当计算器用。
简单的描述参考:http://www.runoob.com/linux/linux-comm-bc.html
而expr命令不支持小数运算,所以需要使用bc进行计算。
语法为:
选项值
- -i:强制进入交互式模式;
- -l:定义使用的标准数学库
- ; -w:对POSIX bc的扩展给出警告信息;
- -q:不打印正常的GNU bc环境信息;
- -v:显示指令版本信息;
- -h:显示指令的帮助信息。
参数
文件:指定包含计算任务的文件。
参考
https://blog.csdn.net/x_i_y_u_e/article/details/50684508