1. 程式人生 > >Linux系統資源獲取並寫入資料庫

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}')
        T
otal_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

最後來看看實現的效果圖: