Linux系统资源获取并写入数据库
一、说明:
之前在做srs流媒体压测时,系统资源相关的数据查看不方便,于是就使用C++ 加上shell脚本,实时获取Linux系统资源情况并将数据写入到数据库中。
二、脚本目录介绍:
流媒体服务器(172.18.152.*3)
脚本目录介绍:
/root/GetSystemInfo //脚本目录
GetSystemInfo.cpp //主程序
cpurate.sh //获取cpu使用率
getsize.sh //获取磁盘空间
memrate.sh //获取内存使用率
network_recev.sh //获取网络接收流量
network_send.sh //获取网络发送流量
getonline.sh //获取在线个数
runtest.sh //编译并运行主程序
推流端(172.18.152.*6)
脚本目录介绍:
/root/ //目录
kill_rtmp_pid.cpp //调用GetPidAndKill.sh脚本
GetPidAndKill.sh //获取pid并杀掉
rtmp_publish_test.sh //开始推流脚本
runtest.sh //编译并运行kill_rtmp_pid.cpp
拉流端(172.18.151.*4)
脚本目录介绍:
/root/ //目录
kill_rtmp_pid.cpp //调用GetPidAndKill.sh脚本
GetPidAndKill.sh //获取pid并杀掉
rtmp_load_test.sh //开始拉流脚本
runtest.sh //编译并运行kill_rtmp_pid.cpp
三、系统资源的获取
1、 cpu使用率获取:
原理是读取系统的 (/proc/stat)文件,然后再提取出想要的数据,再对其进行计算,如图:
第一行的数值表示的是CPU总的使用情况,所以我们只要用第一行的数字计算就可以了。下面对各项参数进行解释说明:
user (1581512)
从系统启动开始累计到当前时刻,用户态的CPU时间,不包含
nice值为负进程。
nice (9124)
从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system (1057303)
从系统启动开始累计到当前时刻,核心时间
idle (267353965)
从系统启动开始累计到当前时刻,除IO等待时间以外其它等待时间
iowait (186130)
从系统启动开始累计到当前时刻,IO等待时间
irq (0)
从系统启动开始累计到当前时刻,硬中断时间
softirq (92740)
从系统启动开始累计到当前时刻,软中断时间
“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。
CPU利用率计算公式:
CPU时间=user+system+nice+idle+iowait+irq+softirq
先取两个采样点,然后计算其差值:
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
下面开始使用shell脚本来获取,脚本如下:
#!/bin/sh
CPULOG_1=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_1=$(echo $CPULOG_1 | awk '{print $4}')
Total_1=$(echo $CPULOG_1 | awk '{print $1+$2+$3+$4+$5+$6+$7}')
sleep 1
CPULOG_2=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_2=$(echo $CPULOG_2 | awk '{print $4}')
Total_2=$(echo $CPULOG_2 | awk '{print $1+$2+$3+$4+$5+$6+$7}')
SYS_IDLE=`expr $SYS_IDLE_2 - $SYS_IDLE_1`
Total=`expr $Total_2 - $Total_1`
SYS_USAGE=`expr $SYS_IDLE/$Total*100 |bc -l`
SYS_Rate=`expr 100-$SYS_USAGE |bc -l`
Disp_SYS_Rate=`expr "scale=3; a=$SYS_Rate/1; if(length(a)==scale(a) && a!=0) print 0;print a" |bc`
echo $Disp_SYS_Rate%
2、内存使用率获取:
原理是读取系统的 (/proc/meminfo)文件,然后再提取出想要的数据,再对其进行计算,脚本如下:
#!/bin/sh
MemTotal=$(cat /proc/meminfo | grep 'MemTotal' | awk '{print $2}')
MemFree=$(cat /proc/meminfo | grep 'MemFree' | awk '{print $2}')
Disp_SYS_Rate=`expr "scale=3; a=100*$MemFree/$MemTotal; if(length(a)==scale(a)) print 0;print a" |bc`
echo $MemTotal
echo $MemFree
echo $Disp_SYS_Rate%
3、网络流量获取:
原理是读取系统的 (/proc/net/dev)文件,然后再提取出想要的数据,再对其进行计算,得出上行速率:
接收(recev):
#!/bin/sh
cat /proc/net/dev | grep 'enp4s0' | awk '{ if($2!=0) print $2}
发送(send):
#!/bin/sh
cat /proc/net/dev | grep 'enp4s0' | awk '{ if($2!=0) print $10/(1024*1024)}'
4、磁盘空间使用率获取:
原理是通过(df -h)命令得到系统磁盘使用情况,然后再提取出想要的数据
#!/bin/bash
LISTEN_PATH=./
if [ -n $1 ]; then
LISTEN_PATH=$1
fi
echo `df -h $LISTEN_PATH | grep "dev" `| awk '{print $3"/"$2}'
磁盘空间使用情况如下:
四、实现:
下面就以获取CPU使用率为例,其他资源的获取也类似:
1、第一步:使用C++代码获取到CPU使用率
//获取Cpu使用率
bool GetCpuRate(std::string& cpurate)
{
FILE *file;
string cmd("./cpurate.sh");
file = popen(cmd.c_str(), "r");
if(file == NULL)
{
cout<<cmd<<" fail"<<endl;
return false;
}
char buf[512] = {0};
while(fgets(buf, sizeof(buf), file) != NULL)
{
char tmpbuf[512]={0};
sscanf(buf,"%s",tmpbuf);
cpurate=std::string(tmpbuf);
}
pclose(file);
return true;
}
2、第二步:将获取CPU的值,写入到数据库:
//连接数据库
if(!mysql_real_connect(&mysql, "localhost", "root", "123456", "srs_linux_systeminfo", 0, NULL, 0))
{
printf("Failed to connect to Mysql!\n");
log_out << "Failed to connect to Mysql!" << endl;
return 0;
}else {
printf("Connected to Mysql successfully!\n");
log_out<<"Connected to Mysql successfully!"<<endl;
}
//创建数据库表(以系统当前时间为表名)
char sqlstr[100];
int create_table_flag;
string TableName=systime;
sprintf(sqlstr,"create table if not exists SRS_Linux_SystemInfo_%s(Id int(32),Time char(60),OnlineCount char(60),CpuRate char(60),MemRate char(60),Network_Recev_Rate char(60),Network_Send_Rate char(60),Network_Recev_Traffic
char(60),Network_Send_Traffic char(60),DiskInfo char(60))",TableName.c_str());
create_table_flag=mysql_real_query(&mysql,sqlstr,strlen(sqlstr));
if(create_table_flag)
{
printf("create table fail!\n");
log_out<<"create table fail!"<<endl;
return 0;
}else {
printf("create table success!\n");
log_out<<"create table success!"<<endl;
}
//插入数据库数据
char sql[300];
sprintf(sql,"insert into SRS_Linux_SystemInfo_%s(Id, Time,OnlineCount, CpuRate, MemRate, Network_Recev_Rate,Network_Send_Rate,Network_Recev_Traffic,Network_Send_Traffic ,DiskInfo) values('%d','%ds','%s','%s','%s','%dKB','%dKB','%sMB','%sMB','%s')
",TableName.c_str(),i,(Interval_TIME*i),onlinecount.c_str(),cpurate.c_str(),memrate.c_str(),(rx_rate/1024/PushClient),(tx_rate/1024/PullClient),network_recev.c_str(),network_send.c_str(),diskInfo.c_str());
flag=mysql_real_query(&mysql,sql,strlen(sql));
if(flag) {
printf("Insert data failure!\n");
return 0;
}else {
printf("Insert data success!\n");
}
备注:
Linux编译C++ 脚本命令:
g++ -o getsysteminfo GetSystemInfo.cpp $(mysql_config --libs)
./getsysteminfo
五、定时执行shell脚本和C++代码:
crontab定时执行脚本:
步骤如下:
1.编辑crontab服务文件,命令如下:
crontab -e
2.输入如下内容,每天晚上定时九点开始执行脚本:
30 21 * * * /root/runcpptest.sh
3.使用命令查看是否添加成功:
crontab -l
4.重启crontab服务生效:
/bin/systemctl restart crond.service
最后来看看实现的效果图: