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
最後來看看實現的效果圖: