Bootstrap

Linux小知识---利用Snmp远程获取CPU,内存和磁盘使用率

知识点回顾

《网络协议学习-SNMP》
前面写了一篇Snmp协议的知识点文章,今天要利用这些知识点,再加一些shell编程知识点,实现一个利用shell脚本,远程获取某个Agent的CPU,内存和硬盘的使用率。
在网上找了半天,也没啥合适的,干脆自己写一个。
在这里插入图片描述

知识点补充

先把常见的OID补充一下,要不都不知道读谁
在这里插入图片描述

系统参数(1.3.6.1.2.1.1)

OID描述备注请求方式
.1.3.6.1.2.1.1.1.0获取系统基本信息SysDescGET
.1.3.6.1.2.1.1.3.0监控时间sysUptimeGET
.1.3.6.1.2.1.1.4.0系统联系人sysContactGET
.1.3.6.1.2.1.1.5.0获取机器名SysNameGET
.1.3.6.1.2.1.1.6.0机器坐在位置SysLocationGET
.1.3.6.1.2.1.1.7.0机器提供的服务SysServiceGET
.1.3.6.1.2.1.25.4.2.1.2系统运行的进程列表hrSWRunNameWALK
.1.3.6.1.2.1.25.6.3.1.2系统安装的软件列表hrSWInstalledNameWALK

网络接口(1.3.6.1.2.1.2)

OID描述备注请求方式
.1.3.6.1.2.1.2.1.0网络接口的数目IfNumberGET
.1.3.6.1.2.1.2.2.1.2网络接口信息描述IfDescrWALK
.1.3.6.1.2.1.2.2.1.3网络接口类型IfTypeWALK
.1.3.6.1.2.1.2.2.1.4接口发送和接收的最大IP数据报[BYTE]IfMTUWALK
.1.3.6.1.2.1.2.2.1.5接口当前带宽[bps]IfSpeedWALK
.1.3.6.1.2.1.2.2.1.6接口的物理地址IfPhysAddressWALK
.1.3.6.1.2.1.2.2.1.8接口当前操作状态[updown]IfOperStatus
.1.3.6.1.2.1.2.2.1.10接口收到的字节数IfInOctetWALK
.1.3.6.1.2.1.2.2.1.16接口发送的字节数IfOutOctetWALK
.1.3.6.1.2.1.2.2.1.11接口收到的数据包个数IfInUcastPktsWALK
.1.3.6.1.2.1.2.2.1.17接口发送的数据包个数IfOutUcastPktsWALK

CPU及负载

OID描述备注请求方式
.1.3.6.1.4.1.2021.11.9.0用户CPU百分比ssCpuUserGET
.1.3.6.1.4.1.2021.11.10.0系统CPU百分比ssCpuSystemGET
.1.3.6.1.4.1.2021.11.11.0空闲CPU百分比ssCpuIdleGET
.1.3.6.1.4.1.2021.11.50.0原始用户CPU使用时间ssCpuRawUserGET
.1.3.6.1.4.1.2021.11.51.0原始nice占用时间ssCpuRawNiceGET
.1.3.6.1.4.1.2021.11.52.0原始系统CPU使用时间ssCpuRawSystem.GET
.1.3.6.1.4.1.2021.11.53.0原始CPU空闲时间ssCpuRawIdleGET
.1.3.6.1.2.1.25.3.3.1.2CPU的当前负载,N个核就有N个负载hrProcessorLoadWALK
. 1.3.6.1.4.1.2021.11.3.0ssSwapInGET
. 1.3.6.1.4.1.2021.11.4.0SsSwapOutGET
. 1.3.6.1.4.1.2021.11.5.0ssIOSentGET
. 1.3.6.1.4.1.2021.11.6.0ssIOReceiveGET
. 1.3.6.1.4.1.2021.11.7.0ssSysInterruptsGET
. 1.3.6.1.4.1.2021.11.8.0ssSysContextGET
. 1.3.6.1.4.1.2021.11.54.0ssCpuRawWaitGET
. 1.3.6.1.4.1.2021.11.56.0ssCpuRawInterruptGET
. 1.3.6.1.4.1.2021.11.57.0ssIORawSentGET
. 1.3.6.1.4.1.2021.11.58.0ssIORawReceivedGET
. 1.3.6.1.4.1.2021.11.59.0ssRawInterruptsGET
. 1.3.6.1.4.1.2021.11.60.0ssRawContextsGET
. 1.3.6.1.4.1.2021.11.61.0ssCpuRawSoftIRQGET
. 1.3.6.1.4.1.2021.11.62.0ssRawSwapIn.GET
. 1.3.6.1.4.1.2021.11.63.0ssRawSwapOutGET
.1.3.6.1.4.1.2021.10.1.3.1Load5GET
.1.3.6.1.4.1.2021.10.1.3.2Load10GET
.1.3.6.1.4.1.2021.10.1.3.3Load15GET

内存及磁盘(1.3.6.1.2.1.25)

OID描述备注请求方式
.1.3.6.1.2.1.25.2.2.0 获取内存大小hrMemorySizeGET
.1.3.6.1.2.1.25.2.3.1.1存储设备编号hrStorageIndexWALK
.1.3.6.1.2.1.25.2.3.1.2存储设备类型hrStorageType[OID]WALK
.1.3.6.1.2.1.25.2.3.1.3存储设备描述hrStorageDescrWALK
.1.3.6.1.2.1.25.2.3.1.4簇的大小hrStorageAllocationUnitsWALK
.1.3.6.1.2.1.25.2.3.1.5簇的的数目hrStorageSizeWALK
.1.3.6.1.2.1.25.2.3.1.6使用多少,跟总容量相除就是占用率hrStorageUsedWALK
.1.3.6.1.4.1.2021.4.3.0Total Swap Size(虚拟内存)memTotalSwapGET
.1.3.6.1.4.1.2021.4.4.0Available Swap SpacememAvailSwapGET
.1.3.6.1.4.1.2021.4.5.0Total RAM in machinememTotalRealGET
.1.3.6.1.4.1.2021.4.6.0Total RAM usedmemAvailRealGET
.1.3.6.1.4.1.2021.4.11.0Total RAM FreememTotalFreeGET
.1.3.6.1.4.1.2021.4.13.0Total RAM SharedmemSharedGET
.1.3.6.1.4.1.2021.4.14.0Total RAM BufferedmemBufferGET
.1.3.6.1.4.1.2021.4.15.0Total Cached MemorymemCachedGET
.1.3.6.1.4.1.2021.9.1.2Path where the disk is mounteddskPathWALK
.1.3.6.1.4.1.2021.9.1.3Path of the device for the partitiondskDeviceWALK
.1.3.6.1.4.1.2021.9.1.6Total size of the disk/partion (kBytes)dskTotalWALK
.1.3.6.1.4.1.2021.9.1.7Available space on the diskdskAvailWALK
.1.3.6.1.4.1.2021.9.1.8Used space on the diskdskUsedWALK
.1.3.6.1.4.1.2021.9.1.9Percentage of space used on diskdskPercentWALK
.1.3.6.1.4.1.2021.9.1.10Percentage of inodes used on diskdskPercentNodeWALK

还有很多,也可以自定义,不过以上这些够运维使用了。
在这里插入图片描述

命令分析

读取用到的命令是snmpget和snmpwalk,参数就不细说了,举两个例子就可以了,按照前面的OID,来获取一下空闲的CPU

[root@localhost 41src_2in1]# snmpget -v 2c -c public 127.0.0.1 .1.3.6.1.4.1.2021.11.11.0       
UCD-SNMP-MIB::ssCpuIdle.0 = INTEGER: 95

可以看到CPU空闲95%,那么学习过数学的我们,一下子就能算出来使用率了。
在这里插入图片描述

获取CPU使用率

那将前面的写法封装成shell的函数即可

cpuu()
{
	cpufree=$(snmpget -v $version -c $public $ipaddr .1.3.6.1.4.1.2021.11.11.0 |cut -d ' ' -f4 )
	cpuused=$[100-cpufree]
	
	if [ $cpufree -gt 0 ];	then 
		echo $cpuused"%"
	else 
		echo ""
	fi
}

这里就涉及到了shell中的数学计算,通过$[x-y]这种写法,就可以计算一个变量的加减乘除,不过仅限于整数操作。小数的写法下面再介绍
在这里插入图片描述

获取内存使用率

思路很简单,先得到空闲内存数,然后得到总的内存数,然后

总内存-空闲内存/总内存

即可得到内存使用率。
这里就涉及到了小数的计算,而且这个数据,必然是小于1的,
先上函数

memu()
{
	memfree=$(snmpget -v $version -c $public $ipaddr .1.3.6.1.4.1.2021.4.6.0|cut -d ' ' -f4)
	memtotal=$(snmpget -v $version -c $public $ipaddr .1.3.6.1.4.1.2021.4.5.0|cut -d ' ' -f4)
	memused=$[memtotal-memfree]

	memusage=$(echo "scale=2; $memused / $memtotal" | bc|cut -d '.' -f2)
	if [ $memusage -gt 0 ];	then 
		echo $memusage"%"
	else 
		echo ""
	fi
}

这里就用到了小数除法的计算,表达方式就是

结果=$(echo "scale=2; $A/ $B" | bc)

其实就是用了bc这个命令,系统中没有的话,需要安装

yum install bc

应该留是通过文件内容,计算结果。感兴趣的可以研究一下
在这里插入图片描述

获取硬盘使用率

这里怕是全网独创了一种写法,因为有时候有了一种思路,就不想再去变通了,为了实现这个思路,可谓是想尽办法。
首先这里试着读了一下总的硬盘大小,失败了

[root@localhost 41src_2in1]# snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.4.1.2021.9.1.6
UCD-SNMP-MIB::dskTotal = No Such Instance currently exists at this OID

然后也没有成功解决这个问题,后来又发现了可以读去簇的数目和使用簇的多少

[root@localhost 41src_2in1]# snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.25.2.3.1.6  
HOST-RESOURCES-MIB::hrStorageUsed.1 = INTEGER: 24010176
HOST-RESOURCES-MIB::hrStorageUsed.3 = INTEGER: 24010176
HOST-RESOURCES-MIB::hrStorageUsed.6 = INTEGER: 5264
HOST-RESOURCES-MIB::hrStorageUsed.7 = INTEGER: 6568376
HOST-RESOURCES-MIB::hrStorageUsed.8 = INTEGER: 733540
HOST-RESOURCES-MIB::hrStorageUsed.10 = INTEGER: 0
HOST-RESOURCES-MIB::hrStorageUsed.35 = INTEGER: 0
HOST-RESOURCES-MIB::hrStorageUsed.37 = INTEGER: 92573
HOST-RESOURCES-MIB::hrStorageUsed.38 = INTEGER: 0
HOST-RESOURCES-MIB::hrStorageUsed.55 = INTEGER: 7819037
HOST-RESOURCES-MIB::hrStorageUsed.60 = INTEGER: 49671
HOST-RESOURCES-MIB::hrStorageUsed.61 = INTEGER: 9096739
HOST-RESOURCES-MIB::hrStorageUsed.65 = INTEGER: 0
[root@localhost 41src_2in1]# snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.25.2.3.1.5 
HOST-RESOURCES-MIB::hrStorageSize.1 = INTEGER: 65400996
HOST-RESOURCES-MIB::hrStorageSize.3 = INTEGER: 98267296
HOST-RESOURCES-MIB::hrStorageSize.6 = INTEGER: 65400996
HOST-RESOURCES-MIB::hrStorageSize.7 = INTEGER: 6568376
HOST-RESOURCES-MIB::hrStorageSize.8 = INTEGER: 733540
HOST-RESOURCES-MIB::hrStorageSize.10 = INTEGER: 32866300
HOST-RESOURCES-MIB::hrStorageSize.35 = INTEGER: 8175124
HOST-RESOURCES-MIB::hrStorageSize.37 = INTEGER: 8175124
HOST-RESOURCES-MIB::hrStorageSize.38 = INTEGER: 8175124
HOST-RESOURCES-MIB::hrStorageSize.55 = INTEGER: 18341120
HOST-RESOURCES-MIB::hrStorageSize.60 = INTEGER: 257536
HOST-RESOURCES-MIB::hrStorageSize.61 = INTEGER: 949451776
HOST-RESOURCES-MIB::hrStorageSize.65 = INTEGER: 1635024

眼前一亮,这不就可以通过加法,计算出来使用比例了吗,我真是太聪明了
在这里插入图片描述
这里还用到了一种列相加的办法,例如一个文件中,有一列数字,那么就可以通过以下的shell方式计算出来

awk '{sum += $1};END {print sum}' /tmp/x.txt

然后总结了写法

snmpwalk -v $version -c $public $ipaddr .1.3.6.1.2.1.25.2.3.1.6 |cut -d ' ' -f4 > /tmp/used.txt  
snmpwalk -v $version -c $public $ipaddr .1.3.6.1.2.1.25.2.3.1.5 |cut -d ' ' -f4 > /tmp/all.txt  
hdused=$(awk '{sum += $1};END {print sum}' /tmp/used.txt) 
hdtotal=$(awk '{sum += $1};END {print sum}' /tmp/all.txt)
hdusage=$(echo "scale=2; $hdused / $hdtotal" | bc|cut -d '.' -f2)
hdusage_new=$(echo -e $hdusage | sed -r 's/0*([0-9])/\1/')
if [ $hdusage_new -gt 0 ];	then 
	echo $hdusage_new"%"
else 
	echo ""
fi

满怀欣喜的结算之后,发现不太对,然后就又发现,原来每个簇的大小不一样。

[root@localhost 41src_2in1]# snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.25.2.3.1.4
HOST-RESOURCES-MIB::hrStorageAllocationUnits.1 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.3 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.6 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.7 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.8 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.10 = INTEGER: 1024 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.35 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.37 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.38 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.55 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.60 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.61 = INTEGER: 4096 Bytes
HOST-RESOURCES-MIB::hrStorageAllocationUnits.65 = INTEGER: 4096 Bytes

在这里插入图片描述
每个部分的大小需要用簇的数量*簇的大小,最终才能相加得到准确大小。
于是得到最终写法

hdu()
{
	rm -rf /tmp/used_fin.txt
	rm -rf /tmp/all_fin.txt
	
	snmpwalk -v $version -c $public $ipaddr .1.3.6.1.2.1.25.2.3.1.6 |cut -d ' ' -f4 >/tmp/used.txt  
	snmpwalk -v $version -c $public $ipaddr .1.3.6.1.2.1.25.2.3.1.5 |cut -d ' ' -f4 >/tmp/all.txt
	snmpwalk -v $version -c $public $ipaddr .1.3.6.1.2.1.25.2.3.1.4 |cut -d ' ' -f4 >/tmp/size.txt
	
	exec 3</tmp/used.txt
	exec 4</tmp/size.txt
	while read line1<&3 && read line2<&4
	do
		echo $[line1*line2] >> /tmp/used_fin.txt
	done

	exec 3</tmp/all.txt
	exec 4</tmp/size.txt
	while read line1<&3 && read line2<&4
	do
		echo $[line1*line2] >> /tmp/all_fin.txt
	done


	hdused=$(awk '{sum += $1};END {print sum}' /tmp/used_fin.txt) 
	hdtotal=$(awk '{sum += $1};END {print sum}' /tmp/all_fin.txt)
	
	echo $hdusage_new"bytes"
	echo $hdtotal"bytes"

	hdusage=$(echo "scale=2; $hdused / $hdtotal" | bc|cut -d '.' -f2)
	hdusage_new=$(echo -e $hdusage | sed -r 's/0*([0-9])/\1/')
	if [ $hdusage_new -gt 0 ];	then 
		echo $hdusage_new"%"
	else 
		echo ""
	fi

}

这里又有一个知识点,就是同时操作两个文件的每一行进行乘法。仔细阅读以下吧。
在这里插入图片描述

完整脚本

《下载地址》
使用例子
脚本名称 获取部分 IP地址 snmp版本 COMMUNITY
例如
分别是,硬盘,CPU和内存的使用率

[root@localhost 41src_2in1]# snmp_get.sh hdu 192.168.32.236 2c public
2%
[root@localhost 41src_2in1]# snmp_get.sh cpuu 192.168.32.236 2c public    
2%
[root@localhost 41src_2in1]# snmp_get.sh memu 192.168.32.236 2c public    
36%

在这里插入图片描述

结束语

一个简单的需求,其实也会包含很多个小的知识点,多点耐心,各个击破,最终肯定能解决问题。
今天在群里见到一个悲伤的故事

在这里插入图片描述
可怜的小孩……
在这里插入图片描述
真正和孩子相处的方法,我觉得还是需要这样
在这里插入图片描述
父母与孩子,还是要共情,而不是一味的教育。
哎,这点表扬我夫人,她做的比我好多了。
我得改正一下。

;