1.需求背景
因为要进行机器系统运行状态信息的一些统计,例如CPU使用率,磁盘使用率等,所以想利用awk与sed对top命令的输出进行处理从而得到想要的数据。
2.实现代码
#! /bin/bash
#set -x
tatol_cpu_usage=0
app_cpu_usage=0
tatol_mem_usage=0
app_mem_usage=0
#进行CPU使用率统计
#Cpu(s): 12.9%us, 3.2%sy, 0.0%ni, 83.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
#top -n表示退出之前刷新的次数,-b表示输出编排成适合输出到文件的格式,一定要加-b选项
#否则得到的idle值不能进行正常处理,而且对其进行dos2unix处理也会显示有不明二进制符号
idle=`top -n 1 -b | sed -e 's/ //g' | \
grep "Cpu(s):" | awk -F ":" '{print $2}' | \
awk -F "," '{print $4}' | awk -F "%" '{print $1}'`
#echo $idle
#以下展示了几种在shell脚本中进行浮点计算的几种方法
#tatol_cpu_usage=$(echo $idle | awk '{printf("%.2f",100-$1)}')
tatol_cpu_usage=$(echo "100-${idle}" | bc)
#tatol_cpu_usage=`echo "100-${idle}" | bc`
echo $tatol_cpu_usage
3.遇到的问题
由于top命令输出结果中并没有直接给出CPU使用率,但是给出了idle即CPU空闲率,所以用100减去它即可得到CPU利用率。利用awk与sed很容易得到idle率中的纯数字字符串。但这个数字是非整数类型的,所以想利用bc命令来处理。
很容易写出如上所以求CPU利用率的代码:
tatol_cpu_usage=`echo "100-${idle}" | bc`
但是脚本执行起来总是显示如下的错误代码:貌似存在控制字符?
[liuhao@my TEST]$ ./info.sh
(standard_in) 1: illegal character: ^[
(standard_in) 1: illegal character: ^[
(standard_in) 1: syntax error
(standard_in) 1: illegal character: ^[
(standard_in) 1: syntax error
(standard_in) 1: illegal character: ^[
(standard_in) 1: illegal character: ^[
(standard_in) 1: syntax error
但是如果在shell里直接执行如下的代码,结果却是正确的
[liuhao@my TEST]$ echo "100-83.8"|bc
16.2
百思不得其解。后来在网上看到shell脚本进行浮点数计算的另一种方法,即利用awk的printf语句:
tatol_cpu_usage=$(echo $idle | awk '{printf("%.2f",100-$1)}')
但是执行结果不如人意:
[liuhao@my TEST]$ ./info.sh
100.00
貌似传递进去的idle总是0。事实越来越说明问题是由top命令输出结果的处理不当而不是因为bc或者awk存在语法或者使用错误引起的,特别是当我用dos2unix命令过滤awk的输出后,会提示:
[liuhao@my TEST]$ ./info.sh
dos2unix: Binary symbol 0x1B found at line 1
dos2unix: Skipping binary file stdin
明显说明确实top的输出即awk与sed处理的数据,也即idle变量的来源的文本格式存在问题。后来经过百度top的用法,看到top有一个-b选项
-b 表示输出编排成适合输出到文件的格式
man top
-b : Batch mode operation
Starts top in ’Batch mode’, which could be useful for sending output from top to
other programs or to a file. In this mode, top will not accept input and runs
until the iterations limit you’ve set with the ’-n’ command-line option or until
killed.
加上-b选项后,脚本运行得到了预期的结果。
一些关于top输出模式的资料介绍:
Batch mode refers to batch processing, which means automated processing, without human intervention. Batch is the opposite of interactive.
In batch mode, top produces output that's more sensible for collecting to a log file or for parsing (though top isn't really good at producing parseable output even in batch mode). There is no limit on the number of output lines and the output doesn't contain any escape sequences for formatting.
In interactive mode, top produces output intended for human viewing. In particular, it only displays one screenful of data. The output contains some escape sequences for formatting. Top operates in interactive mode even when its output is redirected to a file; only the presence of the -b option matters.
后来将top命令不带-b选项的输出重定向到了文件,发现其并不是可批处理的,而是有许多控制字符的东西:
[liuhao@my TEST]$ top -n 1 > a
[liuhao@my TEST]$ vim a
1 ^[[H^[[2J^[(B^[[mtop - 15:25:26 up 9 days, 23:37, 12 users, load average: 7.37, 7.25, 7.21^[(B^[[m^[[39 ;49m^[[K$
2 Tasks:^[(B^[[m^[[39;49m^[(B^[[m 1344 ^[(B^[[m^[[39;49mtotal,^[(B^[[m^[[39;49m^[(B^[[m 7 ^[(B^[[m^[[39; 49mrunning,^[(B^[[m^[[39;49m^[(B^[[m 1337 ^[(B^[[m^[[39;49msleeping,^[(B^[[m^[[39;49m^[(B^[[m 0 ^[(B^[ [m^[[39;49mstopped,^[(B^[[m^[[39;49m^[(B^[[m 0 ^[(B^[[m^[[39;49mzombie^[(B^[[m^[[39;49m^[[K$
3 Cpu(s):^[(B^[[m^[[39;49m^[(B^[[m 12.9%^[(B^[[m^[[39;49mus,^[(B^[[m^[[39;49m^[(B^[[m 2.7%^[(B^[[m^[[39;4 9msy,^[(B^[[m^[[39;49m^[(B^[[m 0.0%^[(B^[[m^[[39;49mni,^[(B^[[m^[[39;49m^[(B^[[m 84.4%^[(B^[[m^[[39;49m id,^[(B^[[m^[[39;49m^[(B^[[m 0.0%^[(B^[[m^[[39;49mwa,^[(B^[[m^[[39;49m^[(B^[[m 0.0%^[(B^[[m^[[39;49mhi ,^[(B^[[m^[[39;49m^[(B^[[m 0.0%^[(B^[[m^[[39;49msi,^[(B^[[m^[[39;49m^[(B^[[m 0.0%^[(B^[[m^[[39;49mst^[ (B^[[m^[[39;49m^[[K$
4 Mem: ^[(B^[[m^[[39;49m^[(B^[[m 65851052k ^[(B^[[m^[[39;49mtotal,^[(B^[[m^[[39;49m^[(B^[[m 54928388k ^[(B ^[[m^[[39;49mused,^[(B^[[m^[[39;49m^[(B^[[m 10922664k ^[(B^[[m^[[39;49mfree,^[(B^[[m^[[39;49m^[(B^[[m 964372k ^[(B^[[m^[[39;49mbuffers^[(B^[[m^[[39;49m^[[K$
5 Swap:^[(B^[[m^[[39;49m^[(B^[[m 32997372k ^[(B^[[m^[[39;49mtotal,^[(B^[[m^[[39;49m^[(B^[[m 0k ^[(B ^[[m^[[39;49mused,^[(B^[[m^[[39;49m^[(B^[[m 32997372k ^[(B^[[m^[[39;49mfree,^[(B^[[m^[[39;49m^[(B^[[m 51 317204k ^[(B^[[m^[[39;49mcached^[(B^[[m^[[39;49m^[[K$
6 ^[[6;1H$
7 ^[[7m PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND ^[(B^[[m^[[39;49m^[[K$
8 ^[(B^[[m^[(B^[[m15587 lipengfe 20 0 23864 1404 1216 R 100.0 0.0 14354:18 32LFSR48 ^[(B^[[m^[[39;49m$
9 ^[(B^[[m^[(B^[[m15695 lipengfe 20 0 14088 3404 984 R 100.0 0.0 14349:04 gpu88 ^[(B^[[m^[[39;49m$
@
:set list