使用Shell脚本采集Linux服务器CPU、内存、网卡、磁盘使用率,并将指标数据封装成JSON,通过UDP协议发送到指定服务
该指标采集脚本使用操作系统 crontab 定时任务每间隔五秒采集一次当前服务器的指标数据
#!/bin/bash
# 设置udp报文发送的IP和端口
sendip="192.168.0.20"
sendport="8888"
# 设置ifconfig命令的绝对路径
ifconfig=/usr/sbin/ifconfig
echo "----------------------------------- CPU -------------------------------------"
# 获取CPU使用率暂停时间(秒)
interval=1
# CPU核心
cpu_num=`cat /proc/stat | grep cpu[0-9] -c`
start_idle=()
start_total=()
cpu_rate=()
CPU_NUM=`grep "physical id" /proc/cpuinfo |sort |uniq |wc -l` # /proc/cpuinfo CPU的相关配置信息
CPU_CORE_NUM=`grep "cores" /proc/cpuinfo |sort |uniq |awk '{print $4}'`
CPU_MODE=`grep "model name" /proc/cpuinfo |sort |uniq |awk -F: '{print $2}'`
cpu_info="{"
cpu_info=$cpu_info"\"cpu_num\":$CPU_NUM,"
cpu_info=$cpu_info"\"cpu_core_num\":$CPU_CORE_NUM,"
cpu_info=$cpu_info"\"cpu_mode\":\"$CPU_MODE\","
# 系统上下文切换次数
ctxt=`cat /proc/stat | grep "ctxt" | awk '{print $2}'`
# 处于Runnable状态的进程个数
procs_running=`cat /proc/stat | grep "procs_running" | awk '{print $2}'`
# 处于等待I/O完成的进程个数
procs_blocked=`cat /proc/stat | grep "procs_blocked" | awk '{print $2}'`
cpu_info=$cpu_info"\"ctxt\":$ctxt,"
cpu_info=$cpu_info"\"procs_running\":$procs_running,"
cpu_info=$cpu_info"\"procs_blocked\":$procs_blocked,"
for((i=0;i<${cpu_num};i++))
{
start=$(cat /proc/stat | grep "cpu$i" | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
start_idle[$i]=$(echo ${start} | awk '{print $4}')
start_total[$i]=$(echo ${start} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
}
start=$(cat /proc/stat | grep "cpu " | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
start_idle[${cpu_num}]=$(echo ${start} | awk '{print $4}')
start_total[${cpu_num}]=$(echo ${start} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
# 睡眠一段时间,计算与上次获取到的使用率差值
sleep ${interval}
# 循环所有的CPU核心,输出CPU使用率
cpu_usage_info="["
for((i=0;i<${cpu_num};i++))
{
end=$(cat /proc/stat | grep "cpu$i" | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
end_idle=$(echo ${end} | awk '{print $4}')
end_total=$(echo ${end} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
idle=`expr ${end_idle} - ${start_idle[$i]}`
total=`expr ${end_total} - ${start_total[$i]}`
idle_normal=`expr ${idle} \* 100`
cpu_usage=`expr ${idle_normal} / ${total}`
cpu_rate[$i]=`expr 100 - ${cpu_usage}`
# echo "CPU$i Rate : ${cpu_rate[$i]}%"
# 拼接每个CPU的时间
cpu_usage_info=$cpu_usage_info"{\"cpu_name\":\"cpu$i\", \"cpu_idle\":$idle, \"cpu_total\":$total, \"cpu_idle_normal\":$idle_normal, \"cpu_usage\":$cpu_usage, \"cpu_rate\":${cpu_rate[$i]}},"
}
end=$(cat /proc/stat | grep "cpu " | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
end_idle=$(echo ${end} | awk '{print $4}')
end_total=$(echo ${end} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
idle=`expr ${end_idle} - ${start_idle[$i]}`
total=`expr ${end_total} - ${start_total[$i]}`
idle_normal=`expr ${idle} \* 100`
cpu_usage=`expr ${idle_normal} / ${total}`
cpu_rate[${cpu_num}]=`expr 100 - ${cpu_usage}`
cpu_usage_info=$cpu_usage_info"{\"cpu_name\":\"cpu\", \"cpu_idle\":$idle, \"cpu_total\":$total, \"cpu_idle_normal\":$idle_normal, \"cpu_usage\":$cpu_usage, \"cpu_rate\":${cpu_rate[${cpu_num}]}}"
cpu_usage_info=$cpu_usage_info"]"
cpu_info=$cpu_info"\"cpu_usage_info\":$cpu_usage_info"
cpu_info=$cpu_info"}"
echo "----------------------------------- Memory -------------------------------------"
mem_total=$(free -m | sed -n '2p' | awk '{print $2}')
mem_used=$(free -m | sed -n '2p' | awk '{print $3}')
mem_free=$(free -m | sed -n '2p' | awk '{print $4}')
mem_shared=$(free -m | sed -n '2p' | awk '{print $5}')
mem_buff=$(free -m | sed -n '2p' | awk '{print $6}')
mem_cached=$(free -m | sed -n '2p' | awk '{print $7}')
mem_rate=`echo "scale=2;$mem_used/$mem_total" | bc | awk -F. '{print $2}'`
mem_info="{\"mem_total\":$mem_total, \"mem_used\":$mem_used, \"mem_free\":$mem_free, \"mem_shared\":$mem_shared, \"mem_buff\":$mem_buff, \"mem_cached\":$mem_cached, \"mem_rate\":$mem_rate, \"unit\": \"MB\"}"
echo "----------------------------------- Disk -------------------------------------"
disk_info="["
DISK_DEV=`df -hP | grep '^/dev/*' | cut -d' ' -f1 | sort`
for disk in $DISK_DEV
do
dev=`df -Ph | grep $disk | awk '{print $1}'`
disk_size=`df -Ph | grep $disk | awk '{print $2}'`
disk_used=`df -Ph | grep $disk | awk '{print $3}'`
disk_free=`df -Ph | grep $disk | awk '{print $4}'`
disk_rate=`df -Ph | grep $disk | awk '{print $5}'`
disk_mount=`df -Ph | grep $disk | awk '{print $6}'`
#echo -e "$disk:\tdisk_size:$disk_size\tused:$disk_used\tdisk_free:$disk_free\tdisk_rate:$disk_rate\tdisk_mount:$disk_mount"
disk_obj_info="{\"name\":\"$disk\", \"disk_mount\":\"$disk_mount\", \"disk_size\":\"$disk_size\",\"disk_used\":\"$disk_used\",\"disk_free\":\"$disk_free\", \"disk_rate\":\"$disk_rate\"},"
disk_info=$disk_info$disk_obj_info
done
# 截取disk_info最后一位的,
disk_info="${disk_info: 0 : ${#disk_info}-1 }]"
echo $disk_info
echo "----------------------------------- Net -------------------------------------"
# 网卡流量采集
net_info="["
# 获取所有网卡设备
#ethn=(`$ifconfig | grep flags|awk '{print $1}'|sed 's/://g'`)
# 不替换网卡设备后面的冒号【:】,否则容易出现xxx-1 xxx的现象,无法区分是哪个网卡设备
ethn=(`$ifconfig | grep flags|awk '{print $1}'`)
# 如果指定网卡,直接使用指定网卡内容
if [ "$1" != "" ];
then
ethn=("$1")
fi
# 先采集网卡内的上行和下行流量信息
ethns=${#ethn[@]}
for ((i=0;i<${ethns};i++))
{
RX_pre=$(cat /proc/net/dev | grep ${ethn[$i]} | sed 's/:/ /g' | awk '{print $2}')
TX_pre=$(cat /proc/net/dev | grep ${ethn[$i]} | sed 's/:/ /g' | awk '{print $10}')
# 睡眠1秒,计算网卡速率的差值
sleep ${interval}
RX_next=$(cat /proc/net/dev | grep ${ethn[$i]} | sed 's/:/ /g' | awk '{print $2}')
TX_next=$(cat /proc/net/dev | grep ${ethn[$i]} | sed 's/:/ /g' | awk '{print $10}')
# 获取上行和下行的带宽
# rx receive 接收,下行流量
# tx transmit 发送,上行流量
RX=$((${RX_next}-${RX_pre}))
TX=$((${TX_next}-${TX_pre}))
# 计算bps
RXMbps=$(echo $RX | awk '{print $1*8/1048576 }')
TXMbps=$(echo $TX | awk '{print $1*8/1048576 }')
RXKbps=$(echo $RX | awk '{print $1*8/1024 }')
TXKbps=$(echo $TX | awk '{print $1*8/1024 }')
# 实际Byte(字节)
RXBYTE=$(printf %.2f $RX)
TXBYTE=$(printf %.2f $TX)
RXKB=$(echo $RX | awk '{print $1/1024 }')
TXKB=$(echo $TX | awk '{print $1/1024 }')
RXMB=$(echo $RX | awk '{print $1/1048576 }')
TXMB=$(echo $TX | awk '{print $1/1048576 }')
device=`echo ${ethn[$i]}|sed 's/://g'`
device_ip=`ifconfig $device |grep "inet "|awk '{print $2}'`
net_info=$net_info"{\"device\":\"${device}\", \"device_ip\":\"$device_ip\", \"RXMbps\":$RXMbps, \"TXMbps\":$TXMbps, \"RXKbps\":$RXKbps, \"TXKbps\":$TXKbps, \"RXByte\":$RXBYTE, \"TXByte\":$TXBYTE, \"RXKByte\":$RXKB, \"TXKByte\":$TXKB, \"RXMByte\":$RXMB, \"TXMByte\":$TXMB},"
}
net_info="${net_info: 0 : ${#net_info}-1 }]"
# 指标采集时间, 取当前操作系统的时间
collect_time=`date +%Y%m%d%H%M%S`
sendmsg="{\"cpu_info\":$cpu_info, \"mem_info\":$mem_info, \"disk_info\":$disk_info, \"net_info\": $net_info, \"collect_time\": $collect_time }"
echo $sendmsg
#echo $sendmsg > /dev/udp/sendip/$sendport
# 使用nc命令发送udp数据报到数据采集服务器 -4 使用IPv4,-u 使用udp数据报
echo $sendmsg | nc -4u $sendip $sendport
-----------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------- 代码分割线 -----------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
# !!!!下方代码写到操作系统的crontab文件中!!!!
# 每5秒钟调度一次当前脚本,由于linux定时机制是以分开始,所以采用下面每分钟间隔5秒执行一次硬件信息采集(脚本路径和名字根据自己的实际文件写)
*/1 * * * * sleep 5 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 10 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 15 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 20 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 25 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 30 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 35 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 40 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 45 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 50 && /opt/project/monitor/monitor.sh
*/1 * * * * sleep 55 && /opt/project/monitor/monitor.sh