將Transforming a WordPress Server Dashboard into a Widget

將Transforming a WordPress Server Dashboard into a Widget

在上一篇文章中,我們創建了插件的基本結構。現在是時候為每個小部件實現渲染類了。

回想一下,所有小部件提供程序都必須實現 Provider 接口。它們還必須位于名為 widget 的文件夾內,并位于名稱空間 AXStatBoardWidget 下。如果我們想添加一種新的指標,只需創建一個相應的類,并創建一個對象并使用 add_provider 方法將其添加到 Widget 類中。

RAM 使用情況小部件

我們想要顯示的第一條信息是當前正在使用的 RAM 量以及當前空閑的 RAM 量。

在本例中,free -m 是我們的朋友 – 它告訴我們 RAM 使用情況。 -m 開關是以兆字節為單位輸出結果。

[vagrant@vagrant-centos64 ~]$ free -m              total       used       free     shared    buffers     cached Mem:           589        366        223          0          9         57 -/+ buffers/cache:        299        290 Swap:            0          0          0 

我們將類命名為 Ram。相應的文件將為 widget/ram.php。我們在這里只是編寫基礎并實現 get_title 。

<?php namespace AXStatBoardWidget;  class Ram implements Provider {   function __construct() {   }    public function get_title() {     return "Ram Usage";   }  ?>

接下來,我們將實現 get_metric 來實際運行必要的 shell 命令并提取信息。稍后我將解釋 get_metric 的更多細節。

<?php function get_metric() {     $df = `free -m | grep -E "(Mem|Swap)" | awk '{print $1, $2, $3, $4}'`;     $df = explode("n", $df);     if ( is_array( $df ) && 2 <= count( $df ) ) {       $df = array_map( function ( $line ) {         if ( empty( $line ) ) {           return;         }         $segment = preg_split( '/s+/', $line );          return array(           'type' => trim( $segment[0]," :" ),           'total' =&gt; (int)$segment[1],           'used' =&gt;  (int)$segment[2],           'free' =&gt;  (int)$segment[3],         );       }, $df );       return $df;     }     return false;   } ?&gt; 

我們執行命令 free -m | grep -E “內存|交換” | awk ‘{print $1, $2, $3, $4}’ .它的輸出看起來與此類似。

[vagrant@vagrant-centos64 ~]$ free -m | grep -E "Mem|Swap" | awk '{print $1, $2, $3, $4}' Mem: 589 541 47 Swap: 255 0 255 [vagrant@vagrant-centos64 ~]$ 

我們通過將行拆分為數組來使用 PHP 解析每一位信息。我們使用 array_map 循環遍歷數組的所有元素,對于每一行,我們用空格分隔,然后返回一個包含元素的關聯數組:

  • type:第一個字段

  • total:第二個字段

  • used:第三個字段
  • free:第四個字段

現在,是 get_content 的時候了。

 public function get_content() {     $metric = $this-&gt;get_metric();     $data = array(       array('Type', 'Used(MB)', 'Free(MB)')     );      foreach ($metric as $item) {       if (empty($item)) {         continue;       }       if ($item['type'] !== 'Mem' &amp;&amp; $item['type'] !== 'Swap') {         continue;       }       if ( 0 == ($item['free'] + $item['used'])) {         continue;       }        $data[] = array(         $item['type'],$item['used'], $item['free']         );     }     $data   =  json_encode($data);     echo 

EOD; } 我們使用積條形圖來顯示 RAM 使用情況。

首先,我們調用 get_metric() 來獲取必要的數據。然后,我們只需循環它并格式化它以匹配 Google 圖表數據要求。最后,我們使用 json_encode 將它們轉換為 JavaScript 對象表示法(或 JSON)。然后,我們輸出一個 html 代碼,其中包含 div 元素來保存圖表對象。

最后,我們調用相應的 Google Chart API 將圖表渲染到 div 元素中。

將Transforming a WordPress Server Dashboard into a Widget

安裝的軟件

我們將介紹的第二個小部件是顯示已安裝軟件的小部件。它是一個小部件,旨在顯示我們在服務器上有哪些常見軟件包以及哪個版本。

例如,我們是否安裝了 NodeJS,是否安裝了 ruby?我們使用的是哪個版本的 PHP?等等。
讓我們使用以下初始內容創建 widget/software.php:

<?php namespace AXStatBoardWidget;  class Software implements Provider {   function __construct() {   }    public function get_title() {     return "Installed Software";   }   function get_metric() {     $cmds = array();      $package = array(       'php'   => '-v',        'node'  =&gt; '-v',       'mysql' =&gt; '-V',        'vim'   =&gt; '--version',       'python' =&gt; '-V',        'ruby'  =&gt; '-v',        'java'  =&gt; '-version',       'cURL'  =&gt; '-V');        foreach ( $package as $cmd=&gt;$version_query ) {       if ( NULL == $cmds[$cmd] = shell_exec( "which $cmd" ) ) {         $cmds[ $cmd ] = 'Not installed';         continue;       }       $version = shell_exec( "$cmd $version_query" );       $version = explode( "n", $version );       if ( is_array( $version ) ) {         $version = array_shift( $version );       }       $cmds[ $cmd ] .= '<br>' . $version;     }     return $cmds;   } 

因此,與往常一樣,我們有 get_title ,它只返回一個簡單的字符串。對于 get_metric(),我們想知道是否安裝了特定的軟件。如果有,則獲取其版本信息。

為此,我們使用顯示軟件版本的開關創建一個命令數組。以PHP為例,php -v 顯示版本信息,mysql –version 顯示MySQL信息。
如果命令返回且錯誤或未找到命令,則 shell_exec 將返回 false。此時,我們可以判斷該軟件沒有安裝;否則,我們可以解析結果以顯示版本信息。然后,我們逐行分割結果,并檢索第一行作為版本信息。這是因為我們需要的信息只能在第一行找到。
對于其他應用程序,某些命令過于冗長,包含許多信息。一旦我們有了數據,就可以創建 get_content 方法了。

  public function get_content() {        $cmds = $this-&gt;get_metric();     $content = '';          foreach ( $cmds as $cmd =&gt; $info ) {       $content .= "<p><strong>$cmd</strong>? $info</p>";     }     echo $content;        } 

我們只是展示此類數據的基本表格。這是顯示時的儀表板:

將Transforming a WordPress Server Dashboard into a Widget

磁盤使用情況

現在我們將解決磁盤使用問題。我們將處理此任務的類命名為 Disk。讓我們先制作基本骨架。

<?php namespace AXStatBoardWidget;  class Disk implements Provider {   function __construct() {   }   public function get_title() {     return "Disk Usage";   } } 

與往常一樣,我們必須實現 Provider 接口。我們在這里為我們的小部件設置一個標題。接下來是我們課程的核心:獲取磁盤使用情況的方法。

<?php function get_metric() {     $df = `df -h`;     $df = explode("n", $df);     if (is_array($df) && count($df)>=2) {       array_shift($df); //Get rid the first line       $df = array_map(function ($line) {         if (empty($line)) {           return NULL;         }         $segment=preg_split('/s+/', $line);          return array(           'filesystem' =&gt; $segment[0],           'size' =&gt; $segment[1],           'used' =&gt; $segment[2],           'available' =&gt; $segment[3],           'use_percent' =&gt; $segment[4],         );       }, $df);       return $df;     }     return false;   } 

在本系列的第一部分中,我們對 df 命令有了一些了解,因此理解以下命令應該很容易:

回想一下 df 輸出:

[vagrant@vagrant-centos64 ~]$ df -h Filesystem            Size  Used Avail Use% Mounted on /dev/sda1             7.3G  1.4G  5.6G  20% / tmpfs                 295M     0  295M   0% /dev/shm /vagrant               60G   55G  4.9G  92% /vagrant /data/GeoIP            60G   55G  4.9G  92% /data/GeoIP /var/webapps           60G   55G  4.9G  92% /var/webapps /var/www/html          60G   55G  4.9G  92% /var/www/html 

我們將其逐行拆分,將其變成數組。我們循環遍歷每一行,用空格分割整行,再次將其轉換為數組。然后,我們只需將值映射為更友好、人類可讀的關聯數組。當我們有了這些數據后,我們可以將其放入 get_content.

  public function get_content() {     $metric = $this-&gt;get_metric();     $data = array(       array( 'Disk', 'Space' )     );      $disk_container = array();     $data_partition = array(       array('Filesystem', 'Free(GB)', 'Used(GB)')     );         foreach ( $metric as $disk ) {       $size = intval( $disk['size'] );       if ( 'M' == substr( $disk['size'], -1 ) ) {         $size = round( $size / 1024, 2 );       }       $used = intval( $disk['used'] );       if ('M' == substr( $disk['used'], -1 ) ) {         $used = round( $used / 1024, 2 );       }        if ( empty( $size ) ) {         continue;       }       $data[] = array( $disk['filesystem'], $size );       $data_partition[] = array($disk['filesystem'], $size - $used, $used);     }   }  

我們遍歷度量數組并嘗試將 MB 空間轉換為 GB 空間。我們構建一個數組來匹配圖表數據格式要求。數據數組應如下所示:

[  ['File System', 'Free', 'Used',   ['/dev/sda1', 10, 24],   ['/dev/sda2', 28, 19]] 

一旦我們有了數據,我們就開始渲染圖表。我們將制作兩個圖表:

  1. 第一個圖表顯示了每個已安裝文件系統的總空間。對于此數據,我們將使用餅圖。

  2. 第二個圖表用于顯示每個已安裝文件系統的磁盤使用情況。為此,我們將使用條形圖。

為此,我們將方法修改為以下內容:

  public function get_content() {     $metric = $this-&gt;get_metric();     $data = array(       array('Disk', 'Space')     );      $disk_container = array();     $data_partition = array(       array('Filesystem', 'Free(GB)', 'Used(GB)')     );         foreach ($metric as $disk) {       $size = intval($disk['size']);       if ('M' == substr($disk['size'], -1)) {         $size = round($size / 1024, 2);       }       $used = intval($disk['used']);       if ('M' == substr($disk['used'], -1)) {         $used = round($used / 1024, 2);       }        if (empty($size)) {         continue;       }       $data[] = array($disk['filesystem'], $size);       $data_partition[] = array($disk['filesystem'], $size - $used, $used);     }     $data = json_encode($data);     $data_partition = json_encode($data_partition);      echo 

EOD; } 我們創建了兩個 div 元素來包含信息

      <div id="widget_disk_usage"></div>       <div id="widget_disk_partion"></div> 

然后,使用圖表 API 的繪制方法將圖表渲染在這些元素內。這里最令人困惑的事情可能是我們圖表的數據格式。

結果如下:

將Transforming a WordPress Server Dashboard into a Widget

服務器信息

這個小部件向我們顯示信息:linux 內核、CPU 架構、正常運行時間、IP 地址。我們這里不需要圖表,一個簡單的數據表就可以完成這項工作。調用該類是Server。這是 widget/server.php

的第一個內容

<?php namespace AXStatBoardWidget; use DateTime;  class Server implements Provider {   function __construct() {   }    public function get_title() {     return "Server Info";   }      /**    * Return server info: OS, Kernel, Uptime, and hostname    * @return array with 3 metric:    *          * hostname    *          * os    *          * uptime    */   function get_metric() {     $server = array();     $server['hostname'] = `hostname`;     $server['os']       = `uname -sr`;     $server['core']     = `grep -c ^processor /proc/cpuinfo`;     $total_uptime_sec = time() - `cut -d. -f1 /proc/uptime`;          $now = new DateTime("now");     $server['uptime'] = $now->diff(new DateTime("@$total_uptime_sec"))-&gt;format('%a days, %h hours, %i minutes and %s seconds');      // Get the external ip with ifconfig.me, a website that show you ip address in plaintext     // when sending request with curl header     $server['ip'] = `curl ifconfig.me`;     $server['ram'] = `free -m | grep Mem | awk '{print $2}'`;     $server['cpu'] =`cat /proc/cpuinfo | grep "model name" | awk '{print $4,$5,$6,$7}'`;      return $server;   }  } 

至此,您應該熟悉 get_title()。我們只是返回這個小部件的標題。

首先,我們使用語句 use DateTime 因為我們位于名稱空間 AXStatBoardWidget 中,并且 DateTime 類來自全局命名空間。每次我們想要使用 DateTime 時,我們都必須輸入 DateTime。因此,我們使用命名空間導入來使 DateTime 名稱在我們當前的命名空間中可用。
將其視為符號鏈接。在 get_metric 中,我們運行 shell 命令來獲取結果并將其分配回來。

主機名

顯示您的服務器主機名。

名稱-sr

顯示Linux內核信息:

[vagrant@vagrant-centos64 ~]$ uname -sr Linux 2.6.32-358.23.2.el6.x86_64 

grep -c ^處理器/proc/cpuinfo

-c 開關打印輸入字符串中匹配行的計數。 /proc/cpuinfo 包含處理器信息。我們 grep 它并計算文字處理器的出現次數。這是我的 32 核結果。

$ grep -c ^processor /proc/cpuinfo 32 

剪切-d。 -f1 /proc/uptime

此命令顯示服務器已啟動并運行的秒數。我們將秒數轉換為“x 天 y 小時 z 分鐘”的格式,以使其更加用戶友好。

使用 DateTime::diff 我們可以輕松實現這一點。我們創建一個帶有當前時間戳的 DateTime 對象,另一個帶有時間戳的對象是當前時間戳減去正常運行時間的秒數。然后使用 format 方法將其格式化為人類友好的字符串。

這是我的結果,正常運行時間為 26194091 秒。

$ cut -d. -f1 /proc/uptime 26194091 

卷曲 ifconfig.me

ifconfig.me 是一項在瀏覽器內直接訪問時顯示您的 IP 地址的服務。如果您使用 curl 向其發送請求,它將以單個字符串形式返回您的 IP 地址。

[vagrant@vagrant-centos64 ~]$ curl ifconfig.me 76.102.253.237 

CPU型號

如上所述,/proc/cpuinfo存儲了CPU信息。我們可以從中提取CPU型號。例如:

[vagrant@vagrant-centos64 ~]$ cat /proc/cpuinfo | grep "model name" | awk '{print $4,$5,$6,$7}' Intel(R) Core(TM) i5-4250U CPU 

一旦我們在數組中獲得了所有可用數據,我們就會返回它并向 get_content 方法提供這些數據。這是 get_content,僅顯示數據:

  public function get_content() {     $server = $this-&gt;get_metric();     echo Ip Address?{$server['ip']}<br><strong>CPU</strong>? {$server['cpu']}<br><strong>Number of Core</strong>? {$server['core']}<br><strong>Ram</strong>? {$server['ram']}<br><strong>Hostname</strong>?{$server['hostname']}<br><strong>OS</strong> {$server['os']}<br><strong>Uptime</strong> {$server['uptime']}<br> EOD;   } 

這是儀表板上的小部件。

將Transforming a WordPress Server Dashboard into a Widget

處理器

監控我們的處理器是其中之一我們可以展示的最重要的東西。我們想知道某個特定進程正在使用多少 CPU 和/或消耗了多少內存。我們將我們的類稱為 Process,首先從 get_title 和 get_metric 開始。我將在代碼后面解釋 get_metric 的更多細節:

<?php namespace AXStatBoardWidget;  class Process implements Provider {     public function get_title() {     return "Processes";   }    /**    * Return server info: OS, Kernel, Uptime, and hostname    * @return array with 3 metric:    *          * hostname    *          * os    *          * uptime    */   function get_metric() {     $processes = array();     $output = `ps -eo pcpu,pmem,pid,user,args,time,start | grep -v '[' | sort -k 1 -r | head -30 | awk '{print $4,$3,$1,$2,$7,$6,$5}'`;     $output = explode("n", $output);     if (!is_array($output) || count($output)<2) {       return false;           }     array_shift($output);     foreach ($output as $line) {       //$line = preg_split('/s+/', $line);       $line = explode(' ', $line);       if (count($line)<6) {         continue;       }       //var_dump($line);       //echo count($line);       if (empty($processes[$line[6]])) {         $processes[$line[6]] = array_combine(array('user', 'pid', '%cpu', '%mem','start','time', 'command'), $line);       } else {         $processes[$line[6]]['%cpu'] += $line[2];         $processes[$line[6]]['%mem'] += $line[3];       }     }      return $processes;   }  }  

顯示進程正在運行的命令是 ps。它通過開關 -e 提供了廣泛的信息,因為它允許我們查看每個進程。對于我們的小部件,我們只需要提取 COU、內存、PID、用戶、參數、時間和啟動。

我們可以結合 -o 表示用戶定義的格式,例如: ps -eo pcpu,pmem,pid,user,args,time,start。如果您嘗試該命令,您將得到一些奇怪的過程,例如:

[vagrant@vagrant-centos64 ~]$ ps -eo pcpu,pmem,pid,user,args,time,start %CPU %MEM   PID USER     COMMAND                         TIME  STARTED  0.0  0.2     1 root     /sbin/init                  00:00:00 06:50:39  0.0  0.0     2 root     [kthreadd]                  00:00:00 06:50:39  0.0  0.0     3 root     [migration/0]               00:00:00 06:50:39 

注意 [kthread]、[migration/0]。基本上,這意味著該命令無法在文件系統中找到。它可能是一些內部系統進程或內核線程,我們可能永遠不想關心它。因此,我們應該使用 grep 來消除這些進程。 grep 有 -v 開關使我們能夠反轉匹配。它返回的結果不包含我們傳遞給它的字符串。

[vagrant@vagrant-centos64 ~]$ ps -eo pcpu,pmem,pid,user,args,time,start | grep -v '[' %CPU %MEM   PID USER     COMMAND                         TIME  STARTED  0.0  0.2     1 root     /sbin/init                  00:00:00 06:50:39  0.0  0.1   292 root     /sbin/udevd -d              00:00:00 06:50:41  0.0  0.1   811 root     /sbin/dhclient -H vagrant-c 00:00:00 06:50:48  0.0  0.2   948 root     /sbin/rsyslogd -i /var/run/ 00:00:00 06:50:50  0.0  0.1   966 rpc      rpcbind                     00:00:00 06:50:50  0.0  0.2   984 rpcuser  rpc.statd                   00:00:00 06:50:50  0.0  0.0  1011 root     rpc.idmapd                  00:00:00 06:50:51  0.0  0.2  1073 root     /usr/sbin/VBoxService       00:00:00 06:50:51 

為了使數據看起來不錯,我們應該按內存或CPU對進程進行排序。在我們的教程中,我們按 %MEM 排序。我們可以使用Linux的sort命令來做到這一點。 %MEM 是第二列。

就像索引為零的數組一樣,第二個元素通過索引鍵 1 訪問。我們可以使用 sort -k 1。它按從最低到最高的順序排序。我們實際上關心的是首先消耗大量內存的進程。為此,我們應該使用 sort -k 1 -r 反轉順序。一旦我們得到結果,我們可能只需要前30個過程。當然,這取決于您,因為您可以選擇包含所有內容,但我想保持簡短。 30 聽起來是一個合理的數字。
最后,我們使用 awk 來格式化輸出。這是我們的命令和示例輸出:

[vagrant@vagrant-centos64 ~]$ ps -eo pcpu,pmem,pid,user,args,time,start | grep -v '[' | sort -k 1 |  head -30 | awk '{print $4,$3,$1,$2,$7,$6,$5}' root 1151 0.0 0.0 00:00:00 -d /sbin/udevd root 1152 0.0 0.0 00:00:00 -d /sbin/udevd root 292 0.0 0.0 00:00:00 -d /sbin/udevd root 811 0.0 0.0 vagrant-c -H /sbin/dhclient root 1 0.0 0.1 06:50:39 00:00:00 /sbin/init root 2153 0.0 0.1 -q -1 /sbin/dhclient root 3642 0.0 0.1 00:00:00 -s /usr/sbin/anacron vagrant 3808 0.0 0.1 pcpu,pmem,pid,user,a -eo ps vagrant 3810 0.0 0.1 1 -k sort vagrant 3811 0.0 0.1 00:00:00 -30 head vagrant 3812 0.0 0.1 $4,$3,$1,$2,$7,$ {print awk root 948 0.0 0.1 /var/run/ -i /sbin/rsyslogd rpc 966 0.0 0.1 06:50:50 00:00:00 rpcbind root 1073 0.0 0.2 06:50:51 00:00:00 /usr/sbin/VBoxService root 1105 0.0 0.2 06:50:51 00:00:00 /usr/sbin/sshd root 1121 0.0 0.2 06:50:52 00:00:00 crond rpcuser 984 0.0 0.2 06:50:50 00:00:00 rpc.statd 496 1088 0.0 0.3 -p -d memcached vagrant 3544 0.0 0.3 00:00:00 vagrant@pts/0 sshd: vagrant 3545 0.0 0.3 06:59:27 00:00:00 -bash root 1113 0.0 1.7 06:50:52 00:00:00 /usr/sbin/httpd apache 1157 0.0 4.2 06:50:53 00:00:01 /usr/sbin/httpd apache 3438 0.0 4.2 06:55:39 00:00:01 /usr/sbin/httpd 

一旦我們得到結果,我們將它分成一個數組并使用 foreach 循環它。我們將同名進程分組到一個元素中,并將 CPU 百分比和內存添加到其中。

<?php //... // inside get_content      foreach ( $output as $line ) {       //$line = preg_split( '/s+/', $line );       $line = explode( ' ', $line );       if ( 6 > count( $line ) ) {         continue;       }       if ( empty( $processes[ $line[6] ] ) ) {         $processes[ $line[6]] = array_combine( array( 'user', 'pid', '%cpu', '%mem','start','time', 'command' ), $line );       } else {         $processes[ $line[6] ]['%cpu'] += $line[2];         $processes[ $line[6] ]['%mem'] += $line[3];       }     } //...     

我們使用 array_combine 從兩個數組創建一個關聯數組:一個用于鍵,一個用于值。

剩下的就是實現 get_content 方法。只是提醒我們必須實現三個方法: get_title, get_metric 和 get_content.對于這個過程,我們只想展示一個簡單的表格。
我們的 get_content 方法很簡單。

  public function get_content() {     $processes = $this-&gt;get_metric();     $html = '
‘; foreach ($processes as $process) { $html .= “

“; } $html .= ‘

User Pid %CPU %Mem Command
{$process[‘user’]} {$process[‘pid’]} {$process[‘%cpu’]} {$process[‘%mem’]} {$process[‘command’]}

‘; echo $html; } 這是我們得到的結果:

將Transforming a WordPress Server Dashboard into a Widget

平均負載

Linux 有一個命令可以顯示過去一分鐘、五分鐘和 15 分鐘內 CPU 和 IO 的平均負載。讓我們把它壓縮成一個小部件。稱之為 Cpuload,并創建我們的 widget/cpuload.php

<?php namespace AXStatBoardWidget;  class Cpuload implements Provider {   function __construct() {   }    public function get_title() {     return "CPU Load";   }   function get_metric() {    $number_of_core = intval(`/bin/grep -c processor /proc/cpuinfo`);    $loadAvg = `cat /proc/loadavg | /usr/bin/awk '{print $1,$2,$3}'`;    $loadAvg = explode(' ', $loadAvg);    if ($loadAvg <3) {      return false;    }    $loadTimes = array('1 min', '5 mins', '15 mins');    return array_map(      function ($loadtime, $value, $number_of_core) {        return array($loadtime, round($value * 100 / $number_of_core, 2), $value);      },        $loadTimes,        $loadAvg,        array_fill(0, 3, $number_of_core)      );  }  } 

首先,我們通過讀取 /proc/cpuinfo 來統計 CPU 核心數,并統計包含“processor”一詞的行數。我們在服務器信息

部分對此進行了介紹。

在Linux中,/proc/loadavg保存平均負載信息。前三列分別是1分鐘、5分鐘和15分鐘的負載。 awk 在這里用于過濾掉我們需要的字段。

?  ~  cat /proc/loadavg 0.01 0.04 0.05 1/217 16089 ?  ~  cat /proc/loadavg | awk '{print $1, $2, $3}' 0.01 0.04 0.05 

將上面的結果用空格分割,構建一個包含三個元素的數組。計算所有核心的平均負載。因此,為了獲得結果,我們使用 array_map 循環遍歷 $loadAvg 數組,并除以我們擁有的核心數。請注意,我們創建了 2 個與 $loadAvg 長度相同的額外數組,一個用于鍵,另一個用于保存核心數,以便將所有這些一一傳遞給 array_map。

get_content 的時間:

  public function get_content() {     $metrics = $this-&gt;get_metric();     if ( ! $metrics ) {       return false;     }     // see https://google-developers.appspot.com/chart/interactive/docs/gallery/barchart#Data_Format for more detai of format     $data = array( array( 'Duration', '% Load' ) );     foreach ( $metrics as $key=&gt;$metric ) {       array_push( $data, array( $metric[0], $metric[1] ) );     }     $data = json_encode( $data );     echo 

EOD; } 我們使用條形圖并從數組創建一個數據數組,然后使用 json_encode 將其轉換為與條形圖數據格式匹配的 JavaScript 表示法數組。

例如:

[ ["Duration","% Load"], ["1 min",20], ["5 mins",11], ["15 mins",3]] 

這是渲染圖表時的結果:

將Transforming a WordPress Server Dashboard into a Widget

以太網接口

我們要處理的下一個小部件是以太網接口。某些服務器可以有多個以太網接口,并為其分配不同的 IP 地址。

看到這些信息非常有用。我們將這個類稱為 Ethernet,從 widget/ethernet.php 的基本內容開始。

<?php /**  * Adopt from https://github.com/afaqurk/linux-dash/blob/master/sh/ip.php  *  */ namespace AXStatBoardWidget;  class Ethernet implements Provider {   function __construct() {   }    public function get_title() {     return "Ethernet";   }    function get_metric() {     $ethernet = array();     $output = shell_exec("ip -oneline link show | awk '{print $2}' | sed 's/://'");     if (!$output) { // It didn't work with "ip" , so we do it with ifconfig       $output = shell_exec(         'ifconfig | /bin/grep -B1 "inet addr" | /usr/bin/awk '' .         '{ if ( $1 == "inet" ) { print $2 }' .         'else if ( $2 == "Link" ) { printf "%s:",$1 } }' | /usr/bin/awk' .         ' -F: '{ print $1","$3 }''       );       $output = trim($output, " n");       $output = `ifconfig | grep "Link encap" | awk '{ print $1 }'`;       $interfaces = explode("n", $output);       $output = `ifconfiga | grep "inet addr" | awk '{ print $2 }' | sed 's/addr://'`;       $addreses = explode("n", $output);       $output = trim($output, " n");       return array_combine($interfaces, $addreses);     }      $output = trim($output, " n");     $interfaces = explode("n", $output);     $addreses = array();     foreach ($interfaces as $interface) {       $output = shell_exec("ip -oneline -family inet addr show $interface | awk '{print $4}' | cut -d'/' -f1");       $addreses[] = $output;     }     return array_combine($interfaces, $addreses);   }  }  

所以小部件的標題將是以太網。對于 get_metric,我們將嘗試獲取所有以太網接口名稱,然后獲取每個接口的 IP 地址,并將設備名稱和 IP 地址結合起來返回。

我們需要處理兩種情況:如果服務器使用 ifconfig 或服務器使用 ip 實用程序。較新的服務器很可能有 ip 而不是 ifconfig;?因此,我們應該首先運行 ip 來獲取以太網設備。
$output = shell_exec("ip -oneline link show | awk '{print $2}' | sed 's/://'"); 

使用 IP 實用程序

帶有 ip 命令和 -oneline 將僅在一行中顯示輸出,其中 link 和 show 將列出所有設備。我們使用 awk 獲取第二列,其中包含設備名稱;但是它包含 : 字符。我們使用 sed 將 : 替換為空字符串。

這是我們在命令行上運行它們時的結果:

[vagrant@vagrant-centos64 sbin]$ ip -oneline link show 1: lo: <loopback> mtu 16436 qdisc noqueue state UNKNOWN     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <broadcast> mtu 1500 qdisc pfifo_fast state UP qlen 1000    link/ether 08:00:27:08:c2:e4 brd ff:ff:ff:ff:ff:ff 3: eth1: <broadcast> mtu 1500 qdisc pfifo_fast state UP qlen 1000    link/ether 08:00:27:eb:11:e4 brd ff:ff:ff:ff:ff:ff [vagrant@vagrant-centos64 sbin]$ ip -oneline link show | awk '{print $2}' lo: eth0: eth1: [vagrant@vagrant-centos64 sbin]$ ip -oneline link show | awk '{print $2}' | sed 's/://' lo eth0 eth1 [vagrant@vagrant-centos64 sbin]$ </broadcast></broadcast></loopback>

如果 shell_exec 成功運行,我們將繼續使用 IP 實用程序。上面的輸出被逐行分割成一個數組。

$output = trim($output, " n"); $interfaces = explode("n", $output); 

然后我們循環遍歷該數組,并再次使用 ip 命令 ip -oneline -family inet addr show device_name 來獲取分配給設備的 IP 地址。

    $addreses = array();     foreach ($interfaces as $interface) {       $output = shell_exec("ip -oneline -family inet addr show $interface | awk '{print $4}' | cut -d'/' -f1");       $addreses[] = $output;     } 

IP 地址出現在第四列中,因此 awk 用于打印該值。然后我們使用 cut 將命令按 / 分割,并使用 swich -f1 獲取第一個元素。

查看輸出,看看當我們在命令行上運行它們時,它們是如何工作的:

[vagrant@vagrant-centos64 sbin]$ ip -oneline -family inet addr show eth1 3: eth1    inet 192.168.1.111/24 brd 192.168.1.255 scope global eth1 [vagrant@vagrant-centos64 sbin]$ ip -oneline -family inet addr show eth1 | awk '{print $4}' 192.168.1.111/24 [vagrant@vagrant-centos64 sbin]$ ip -oneline -family inet addr show eth1 | awk '{print $4}' | cut -d'/' -f1 192.168.1.111 [vagrant@vagrant-centos64 sbin]$ 

當我們在接口數組中獲取設備名稱并在地址數組中獲取 IP 地址時,我們創建一個關聯數組,其中接口名稱作為鍵,IP 地址作為值。

return array_combine($interfaces, $addreses); 

使用 ifconfig 的服務器

在 ifconfig 的情況下,ip 的 shell_exec 將返回 false。在這種情況下,我們改為運行 ifconfig。

我們上面介紹的邏輯完全相同 – 它只是獲取信息的不同實用程序。

    if (!$output) { // It didn't work with "ip" , so we do it with ifconfig       $output = `ifconfig | grep "Link encap" | awk '{ print $1 }'`;       $interfaces = explode("n", $output);       $output = `ifconfig | grep "inet addr" | awk '{ print $2 }' | sed 's/addr://'`;       $addreses = explode("n", $output);       $output = trim($output, " n");       return array_combine($interfaces, $addreses);     } 

讓我們在終端中運行上面的命令,以便我們了解發生了什么。

請注意,ifconfig 直接在輸出中顯示 IP 地址,因此我們可以直接獲取它們,而不是在設備數組上運行循環并獲取每個設備的 IP 地址。

[vagrant@vagrant-centos64 sbin]$ ifconfig eth0      Link encap:Ethernet  HWaddr 08:00:27:08:C2:E4           inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0           inet6 addr: fe80::a00:27ff:fe08:c2e4/64 Scope:Link           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1           RX packets:4230 errors:0 dropped:0 overruns:0 frame:0           TX packets:2575 errors:0 dropped:0 overruns:0 carrier:0           collisions:0 txqueuelen:1000           RX bytes:444488 (434.0 KiB)  TX bytes:2288676 (2.1 MiB)  eth1      Link encap:Ethernet  HWaddr 08:00:27:EB:11:E4           inet addr:192.168.1.111  Bcast:192.168.1.255  Mask:255.255.255.0           inet6 addr: fe80::a00:27ff:feeb:11e4/64 Scope:Link           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1           RX packets:4470 errors:0 dropped:0 overruns:0 frame:0           TX packets:2449 errors:0 dropped:0 overruns:0 carrier:0           collisions:0 txqueuelen:1000           RX bytes:1689803 (1.6 MiB)  TX bytes:271675 (265.3 KiB)  lo        Link encap:Local Loopback           inet addr:127.0.0.1  Mask:255.0.0.0           inet6 addr: ::1/128 Scope:Host           UP LOOPBACK RUNNING  MTU:16436  Metric:1           RX packets:264 errors:0 dropped:0 overruns:0 frame:0           TX packets:264 errors:0 dropped:0 overruns:0 carrier:0           collisions:0 txqueuelen:0           RX bytes:15840 (15.4 KiB)  TX bytes:15840 (15.4 KiB)  [vagrant@vagrant-centos64 sbin]$ ifconfig | grep "Link encap" eth0      Link encap:Ethernet  HWaddr 08:00:27:08:C2:E4 eth1      Link encap:Ethernet  HWaddr 08:00:27:EB:11:E4 lo        Link encap:Local Loopback [vagrant@vagrant-centos64 sbin]$ ifconfig | grep "Link encap" | awk '{ print $1 }' eth0 eth1 lo  [vagrant@vagrant-centos64 sbin]$ ifconfig | grep "inet addr"           inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0           inet addr:192.168.1.111  Bcast:192.168.1.255  Mask:255.255.255.0           inet addr:127.0.0.1  Mask:255.0.0.0 [vagrant@vagrant-centos64 sbin]$ ifconfig | grep "inet addr" | awk '{ print $2 }' addr:10.0.2.15 addr:192.168.1.111 addr:127.0.0.1 [vagrant@vagrant-centos64 sbin]$ ifconfig | grep "inet addr" | awk '{ print $2 }' | sed 's/addr://' 10.0.2.15 192.168.1.111 127.0.0.1 [vagrant@vagrant-centos64 sbin]$ 

一旦我們有了數據,將它們放入 get_content 中就很容易了,因為我們在這里只顯示了一個簡單的表格。

  public function get_content() {     $interfaces = $this-&gt;get_metric();     $html = '
‘; foreach ( $interfaces as $interface => $ip ) { $html .= “

“; } $html .= ‘

Interface IP
{$interface} {$ip}

‘; echo $html; } 以下是它向管理員顯示的方式:

將Transforming a WordPress Server Dashboard into a Widget

網絡流量

網絡流量或網絡 IO 顯示通過計算機網絡傳輸包的狀態。該信息是從 netstat 中提取的。

[vagrant@vagrant-centos64 sbin]$ netstat -i Kernel Interface table Iface       MTU Met    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg eth0       1500   0     4828      0      0      0     2933      0      0      0 BMRU eth1       1500   0     4806      0      0      0     2679      0      0      0 BMRU lo        16436   0      276      0      0      0      276      0      0      0 LRU 

讓我們在文件 widget/networkio.php 中獲取我們的基本類 Networkio

<?php /**  * Adopt from https://github.com/afaqurk/linux-dash/blob/master/sh/ip.php  *  */ namespace AXStatBoardWidget;  class Networkio implements Provider {   function __construct() {   }    public function get_title() {     return "Network IO";   }   function get_metric() {    $ethernet = array();       $output = `netstat -i | grep -v -E '(Iface|Interface)' | awk '{print $1","$4","$8}'`;    $lines = explode("n", $output);    foreach ($lines as $line) {      $line = explode(',', $line);      if (count($line)<3) {        continue;      }      $ethernet[] = array($line[0], intval($line[1]), intval($line[2]));    }    return $ethernet;  }}  

我將在本文后面解釋它們。現在,讓我們嘗試評估我們在上面代碼中使用的命令。

我將嘗試運行多個命令,以便在我們將結果傳遞到另一個管道后您可以理解其中的差異。

[vagrant@vagrant-centos64 sbin]$ netstat -i Kernel Interface table Iface       MTU Met    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg eth0       1500   0     5727      0      0      0     3400      0      0      0 BMRU eth1       1500   0     5004      0      0      0     2797      0      0      0 BMRU lo        16436   0      292      0      0      0      292      0      0      0 LRU  [vagrant@vagrant-centos64 sbin]$ netstat -i | grep -v -E '(Iface|Interface)' eth0       1500   0     5736      0      0      0     3405      0      0      0 BMRU eth1       1500   0     5004      0      0      0     2797      0      0      0 BMRU lo        16436   0      292      0      0      0      292      0      0      0 LRU  [vagrant@vagrant-centos64 sbin]$ netstat -i | grep -v -E '(Iface|Interface)' | awk '{print $1","$4","$8}' eth0,5760,3420 eth1,5004,2797 lo,292,292 [vagrant@vagrant-centos64 sbin]$ 

netstat 返回很多東西,我們使用 grep 來排除包含單詞 IfaceKernel 的行(前兩行),我們只關心最后三行是我們的以太網設備及其包傳輸。 awk 用于打印出第一、四、八列的數據,分別表示接口名稱、RX-OK、TX-OK。

在我們的get_metric中,我們將結果逐行拆分到一個數組中。因為每一行都包含用逗號分隔的數據,所以它們被再次分割成一個數組。

我們確保只接受具有三個元素的數組。我們還嘗試將數字字符串轉換為整數值。數據將依次輸入 get_content。

  public function get_content() {     $interfaces = $this-&gt;get_metric();     $data = array_merge(array(array('Interface', 'Receive(package)', 'Transfer(package)')), $interfaces);     $data = json_encode($data);      echo 

EOD; } 我們之前使用了條形圖,并嘗試將指標數據數組格式化為條形圖數據格式,然后進行渲染。

數據數組的每一行代表一個組條形圖,其中包含條形圖名稱及其相應的值。在我們的例子中,每一行都是接口名稱以及 RX 欄和 TX 欄。
這是我們得到的:

將Transforming a WordPress Server Dashboard into a Widget

輸入/輸出統計

現在,我們處理 io stat。 IO 表示輸入/輸出。我們將了解每秒執行多少次讀/寫操作。我們還處理 io_wait。 IO等待是CPU空閑等待從硬盤讀取結果的時間。

比如你正在讀取MySQL數據,CPU會空閑下來等待結果。 io wait 按1秒或1000毫秒計算。如果您的代碼需要 100 毫秒從硬盤讀取數據,則 io_wait 為 100/1000 = 10%。 IO 等待越少,系統性能越好。

為了繼續執行此操作,請確保系統上有 sysstat 軟件包。

  1. 對于 Arch Linux,使用 pacman -S sysstat 安裝

  2. 對于 debian/ubuntu,您可以使用 apt-get install sysstat 獲取它們

  3. 對于 Fedora/Centos,您可以使用 yum install sysstat
  4. 對于其他發行版,:請使用您的發行版包管理器進行安裝

安裝完成后,讓我們評估一下我們將使用的一些命令。首先是第一件事:

[vagrant@vagrant-centos64 sbin]$ iostat Linux 2.6.32-358.23.2.el6.x86_64 (vagrant-centos64.vagrantup.com)     04/27/2014 	_x86_64_	(1 CPU)  avg-cpu:  %user   %nice %system %iowait  %steal   %idle            0.05    0.00    0.25    0.04    0.00   99.66  Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn sda               0.18         7.62         1.04     157826      21584 

第四行包含IO狀態數據。我們對第四列中的 iowait 值感興趣。從第七行開始的數據包含硬盤驅動器每秒的讀/寫塊。

如果您有許多硬盤連接到服務器,您將擁有多個設備:sdb、sdc 等。
數據是塊的數量,而不是實際大小(以兆字節為單位)。我們必須找到塊大小來計算總大小。
塊大小存儲在/sys/block/sda/queue/physical_block_size中。

[vagrant@vagrant-centos64 ~]$ cat /sys/block/sda/queue/physical_block_size 512 [vagrant@vagrant-centos64 ~]$ 

所以我的sda的塊大小是512。我們將每秒讀取的塊數與塊大小相乘,得到讀/寫數據的實際大小。

有了上面的基本知識,讓我們在 widget/iostat.php 中創建我們的類 Iostat 。

<?php namespace AXStatBoardWidget;  class Iostat implements Provider {   function __construct() {   }    public function get_title() {     return "Disk IO";   }     /**    * Make sure we install package sysstat    * yum install sysstat    * or apt-get install sysstat    *    * Return IO Stat information. CPU waiting time, disk read/write    *    */   function get_metric() {     $metric = array();      $output = `iostat`;     $number_of_core = intval(`/bin/grep -c processor /proc/cpuinfo`);      $lines = explode("n", $output);     //We should have more than  4 lines     if (!is_array($lines) || sizeof($lines)<4) {       return false;     }     $avg_cpu = preg_split("/s+/", $lines[3]);     $metric['cpu'] = array(       'user'    => floatval($avg_cpu[0]) * $number_of_core,       'system'  =&gt; floatval($avg_cpu[2]) * $number_of_core,       'io_wait' =&gt; floatval($avg_cpu[3]) * $number_of_core,       'other'   =&gt; 100 - ($avg_cpu[0] + $avg_cpu[2] + $avg_cpu[3])     );          if (sizeof($lines) &gt;=7) {       for ($i=6,$l = sizeof($lines);$i floatval($line[2]) * $block_size / 1024,           'write' =&gt; floatval($line[3]) * $block_size / 1024,         );        }       }      return $metric;   }  }  

我們只是嘗試將我們的理論應用到 PHP 代碼中。獲取 iostat 的輸出,將其轉換為數組,每一行都是一個元素。

第四行被空格分割并映射到關聯數組中。第七行之后的所有行都放入另一個關聯數組中,其中鍵是設備名稱(sda,sdb,sdc,..),如果以兆字節為單位讀取和寫入,則值是一個數組。
一旦我們獲得了指標,將其輸入 get_content 并渲染我們的圖表。

  public function get_content() {     $metric = $this-&gt;get_metric();     $disk_io = array(       array('Disk', 'Read(MB)', 'Write(MB)'),     );     foreach ($metric['disk'] as $disk=&gt;$stat) {       $disk_io[] = array($disk, $stat['read'], $stat['write']);     }     $disk_io = json_encode($disk_io);           $cpu_io = json_encode(array(       array('CPU Time', 'Percent'),       array('IO Wait', $metric['cpu']['io_wait']),     ));          echo 

EOD; } 對于磁盤 IO 讀寫,我們使用了條形圖。對于 IO 等待,我們使用儀表圖來使其看起來更漂亮。我們認為 80-100 的 IOwait 是一個嚴重事件,并用紅色突出顯示。

將Transforming a WordPress Server Dashboard into a Widget

? 版權聲明
THE END
喜歡就支持一下吧
點贊7 分享