亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Table of Contents
RAM 使用情況小部件
磁盤使用情況
服務(wù)器信息
主機(jī)名
名稱-sr
grep -c ^處理器/proc/cpuinfo
CPU型號(hào)
處理器
以太網(wǎng)接口
使用 ifconfig 的服務(wù)器
網(wǎng)絡(luò)流量
輸入/輸出統(tǒng)計(jì)
Home CMS Tutorial WordPress 將Transforming a WordPress Server Dashboard into a Widget

將Transforming a WordPress Server Dashboard into a Widget

Sep 03, 2023 pm 09:13 PM

將Transforming a WordPress Server Dashboard into a Widget

在上一篇文章中,我們創(chuàng)建了插件的基本結(jié)構(gòu)。現(xiàn)在是時(shí)候?yàn)槊總€(gè)小部件實(shí)現(xiàn)渲染類了。

回想一下,所有小部件提供程序都必須實(shí)現(xiàn) Provider 接口。它們還必須位于名為 widget 的文件夾內(nèi),并位于名稱空間 AX\StatBoard\Widget 下。如果我們想添加一種新的指標(biāo),只需創(chuàng)建一個(gè)相應(yīng)的類,并創(chuàng)建一個(gè)對(duì)象并使用 add_provider 方法將其添加到 Widget 類中。

RAM 使用情況小部件

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

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

[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。相應(yīng)的文件將為 widget/ram.php。我們?cè)谶@里只是編寫基礎(chǔ)并實(shí)現(xiàn) get_title 。

<?php
namespace AX\StatBoard\Widget;

class Ram implements Provider {
  function __construct() {
  }

  public function get_title() {
    return "Ram Usage";
  }

?>
接下來,我們將實(shí)現(xiàn) get_metric 來實(shí)際運(yùn)行必要的 shell 命令并提取信息。稍后我將解釋 get_metric 的更多細(xì)節(jié)。
<?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' => (int)$segment[1],
          'used' =>  (int)$segment[2],
          'free' =>  (int)$segment[3],
        );
      }, $df );
      return $df;
    }
    return false;
  }
?>
我們執(zhí)行命令 free -m | grep -E "內(nèi)存|交換" | 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 ~]$
我們通過將行拆分為數(shù)組來使用 PHP 解析每一位信息。我們使用 array_map 循環(huán)遍歷數(shù)組的所有元素,對(duì)于每一行,我們用空格分隔,然后返回一個(gè)包含元素的關(guān)聯(lián)數(shù)組:

  • type:第一個(gè)字段

  • total:第二個(gè)字段

  • used:第三個(gè)字段
  • free:第四個(gè)字段

現(xiàn)在,是 get_content 的時(shí)候了。
 public function get_content() {
    $metric = $this->get_metric();
    $data = array(
      array('Type', 'Used(MB)', 'Free(MB)')
    );

    foreach ($metric as $item) {
      if (empty($item)) {
        continue;
      }
      if ($item['type'] !== 'Mem' && $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
      <div id="widget_ram_usage"></div>
      <script type="text/javascript">
      google.setOnLoadCallback(function () {
        var data = google.visualization.arrayToDataTable({$data});
        var options = {
          isStacked: true
        };
        var chart = new google.visualization.ColumnChart(document.getElementById('widget_ram_usage'));
        chart.draw(data, options);
      })        
    </script>
EOD;
  }
我們使用堆積條形圖來顯示 RAM 使用情況。

首先,我們調(diào)用 get_metric() 來獲取必要的數(shù)據(jù)。然后,我們只需循環(huán)它并格式化它以匹配 Google 圖表數(shù)據(jù)要求。最后,我們使用 json_encode 將它們轉(zhuǎn)換為 JavaScript 對(duì)象表示法(或 JSON)。然后,我們輸出一個(gè) HTML 代碼,其中包含 div 元素來保存圖表對(duì)象。

最后,我們調(diào)用相應(yīng)的 Google Chart API 將圖表渲染到 div 元素中。

將Transforming a WordPress Server Dashboard into a Widget

安裝的軟件

我們將介紹的第二個(gè)小部件是顯示已安裝軟件的小部件。它是一個(gè)小部件,旨在顯示我們?cè)诜?wù)器上有哪些常見軟件包以及哪個(gè)版本。

例如,我們是否安裝了 NodeJS,是否安裝了 Ruby?我們使用的是哪個(gè)版本的 PHP?等等。

讓我們使用以下初始內(nèi)容創(chuàng)建 widget/software.php
<?php
namespace AX\StatBoard\Widget;

class Software implements Provider {
  function __construct() {
  }

  public function get_title() {
    return "Installed Software";
  }
  function get_metric() {
    $cmds = array();

    $package = array(
      'php'   => '-v', 
      'node'  => '-v',
      'mysql' => '-V', 
      'vim'   => '--version',
      'python' => '-V', 
      'ruby'  => '-v', 
      'java'  => '-version',
      'curl'  => '-V');
  
    foreach ( $package as $cmd=>$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 ,它只返回一個(gè)簡單的字符串。對(duì)于 get_metric(),我們想知道是否安裝了特定的軟件。如果有,則獲取其版本信息。

為此,我們使用顯示軟件版本的開關(guān)創(chuàng)建一個(gè)命令數(shù)組。以PHP為例,php -v 顯示版本信息,mysql --version 顯示MySQL信息。

如果命令返回且錯(cuò)誤或未找到命令,則 shell_exec 將返回 false。此時(shí),我們可以判斷該軟件沒有安裝;否則,我們可以解析結(jié)果以顯示版本信息。然后,我們逐行分割結(jié)果,并檢索第一行作為版本信息。這是因?yàn)槲覀冃枰男畔⒅荒茉诘谝恍姓业健?

對(duì)于其他應(yīng)用程序,某些命令過于冗長,包含許多信息。一旦我們有了數(shù)據(jù),就可以創(chuàng)建 get_content 方法了。

  public function get_content() {
  
    $cmds = $this->get_metric();
    $content = '';
    
    foreach ( $cmds as $cmd => $info ) {
      $content .= "<p><strong>$cmd</strong>  $info</p>";
    }
    echo $content;
    
  }
我們只是展示此類數(shù)據(jù)的基本表格。這是顯示時(shí)的儀表板:

將Transforming a WordPress Server Dashboard into a Widget

磁盤使用情況

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

<?php
namespace AX\StatBoard\Widget;

class Disk implements Provider {
  function __construct() {
  }
  public function get_title() {
    return "Disk Usage";
  }
}
與往常一樣,我們必須實(shí)現(xiàn) Provider 接口。我們?cè)谶@里為我們的小部件設(shè)置一個(gè)標(biāo)題。接下來是我們課程的核心:獲取磁盤使用情況的方法。

<?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' => $segment[0],
          'size' => $segment[1],
          'used' => $segment[2],
          'available' => $segment[3],
          'use_percent' => $segment[4],
        );
      }, $df);
      return $df;
    }
    return false;
  }
在本系列的第一部分中,我們對(duì) df 命令有了一些了解,因此理解以下命令應(yīng)該很容易:

回想一下 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
我們將其逐行拆分,將其變成數(shù)組。我們循環(huán)遍歷每一行,用空格分割整行,再次將其轉(zhuǎn)換為數(shù)組。然后,我們只需將值映射為更友好、人類可讀的關(guān)聯(lián)數(shù)組。當(dāng)我們有了這些數(shù)據(jù)后,我們可以將其放入 get_content.

  public function get_content() {
    $metric = $this->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);
    }
  }

我們遍歷度量數(shù)組并嘗試將 MB 空間轉(zhuǎn)換為 GB 空間。我們構(gòu)建一個(gè)數(shù)組來匹配圖表數(shù)據(jù)格式要求。數(shù)據(jù)數(shù)組應(yīng)如下所示:

[  ['File System', 'Free', 'Used',
  ['/dev/sda1', 10, 24],
  ['/dev/sda2', 28, 19]]
一旦我們有了數(shù)據(jù),我們就開始渲染圖表。我們將制作兩個(gè)圖表:
  1. 第一個(gè)圖表顯示了每個(gè)已安裝文件系統(tǒng)的總空間。對(duì)于此數(shù)據(jù),我們將使用餅圖。

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

為此,我們將方法修改為以下內(nèi)容:

  public function get_content() {
    $metric = $this->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 id="widget_disk_usage"></div>
      <div id="widget_disk_partion"></div>
      <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(function () {
        var data = google.visualization.arrayToDataTable({$data});
        var options = {
          is3D: true,
        };
        var chart = new google.visualization.PieChart(document.getElementById('widget_disk_usage'));
        chart.draw(data, options);

        var data2 = google.visualization.arrayToDataTable({$data_partition});
        var options2 = {
          isStacked: true
        };
        var chart2 = new google.visualization.ColumnChart(document.getElementById('widget_disk_partion'));
        chart2.draw(data2, options2);

      })        
    </script>
EOD;
  }
我們創(chuàng)建了兩個(gè) div 元素來包含信息
      <div id="widget_disk_usage"></div>
      <div id="widget_disk_partion"></div>
然后,使用圖表 API 的繪制方法將圖表渲染在這些元素內(nèi)。這里最令人困惑的事情可能是我們圖表的數(shù)據(jù)格式。

結(jié)果如下:

將Transforming a WordPress Server Dashboard into a Widget

服務(wù)器信息

這個(gè)小部件向我們顯示信息:Linux 內(nèi)核、CPU 架構(gòu)、正常運(yùn)行時(shí)間、IP 地址。我們這里不需要圖表,一個(gè)簡單的數(shù)據(jù)表就可以完成這項(xiàng)工作。調(diào)用該類是Server。這是 widget/server.php

的第一個(gè)內(nèi)容
<?php
namespace AX\StatBoard\Widget;
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"))->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;
  }

}
至此,您應(yīng)該熟悉 get_title()。我們只是返回這個(gè)小部件的標(biāo)題。

首先,我們使用語句 use DateTime 因?yàn)槲覀兾挥诿Q空間 AX\StatBoard\Widget 中,并且 DateTime 類來自全局命名空間。每次我們想要使用 DateTime 時(shí),我們都必須輸入 \DateTime。因此,我們使用命名空間導(dǎo)入來使 DateTime 名稱在我們當(dāng)前的命名空間中可用。

將其視為符號(hào)鏈接。在 get_metric 中,我們運(yùn)行 shell 命令來獲取結(jié)果并將其分配回來。

主機(jī)名

顯示您的服務(wù)器主機(jī)名。

名稱-sr

顯示Linux內(nèi)核信息:

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

grep -c ^處理器/proc/cpuinfo

-c 開關(guān)打印輸入字符串中匹配行的計(jì)數(shù)。 /proc/cpuinfo 包含處理器信息。我們 grep 它并計(jì)算文字處理器的出現(xiàn)次數(shù)。這是我的 32 核結(jié)果。

$ grep -c ^processor /proc/cpuinfo
32

剪切-d。 -f1 /proc/uptime

此命令顯示服務(wù)器已啟動(dòng)并運(yùn)行的秒數(shù)。我們將秒數(shù)轉(zhuǎn)換為“x 天 y 小時(shí) z 分鐘”的格式,以使其更加用戶友好。

使用 DateTime::diff 我們可以輕松實(shí)現(xiàn)這一點(diǎn)。我們創(chuàng)建一個(gè)帶有當(dāng)前時(shí)間戳的 DateTime 對(duì)象,另一個(gè)帶有時(shí)間戳的對(duì)象是當(dāng)前時(shí)間戳減去正常運(yùn)行時(shí)間的秒數(shù)。然后使用 format 方法將其格式化為人類友好的字符串。

這是我的結(jié)果,正常運(yùn)行時(shí)間為 26194091 秒。

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

卷曲 ifconfig.me

ifconfig.me 是一項(xiàng)在瀏覽器內(nèi)直接訪問時(shí)顯示您的 IP 地址的服務(wù)。如果您使用 curl 向其發(fā)送請(qǐng)求,它將以單個(gè)字符串形式返回您的 IP 地址。

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

CPU型號(hào)

如上所述,/proc/cpuinfo存儲(chǔ)了CPU信息。我們可以從中提取CPU型號(hào)。例如:
[vagrant@vagrant-centos64 ~]$ cat /proc/cpuinfo | grep "model name" | awk '{print $4,$5,$6,$7}'
Intel(R) Core(TM) i5-4250U CPU
一旦我們?cè)跀?shù)組中獲得了所有可用數(shù)據(jù),我們就會(huì)返回它并向 get_content 方法提供這些數(shù)據(jù)。這是 get_content,僅顯示數(shù)據(jù):

  public function get_content() {
    $server = $this->get_metric();
    echo <<<EOD
    <strong>Ip Address</strong> {$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

處理器

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

<?php
namespace AX\StatBoard\Widget;

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;
  }

}

顯示進(jìn)程正在運(yùn)行的命令是 ps。它通過開關(guān) -e 提供了廣泛的信息,因?yàn)樗试S我們查看每個(gè)進(jìn)程。對(duì)于我們的小部件,我們只需要提取 COU、內(nèi)存、PID、用戶、參數(shù)、時(shí)間和啟動(dòng)。

我們可以結(jié)合 -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]?;旧?,這意味著該命令無法在文件系統(tǒng)中找到。它可能是一些內(nèi)部系統(tǒng)進(jìn)程或內(nèi)核線程,我們可能永遠(yuǎn)不想關(guān)心它。因此,我們應(yīng)該使用 grep 來消除這些進(jìn)程。 grep 有 -v 開關(guān)使我們能夠反轉(zhuǎn)匹配。它返回的結(jié)果不包含我們傳遞給它的字符串。

[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
為了使數(shù)據(jù)看起來不錯(cuò),我們應(yīng)該按內(nèi)存或CPU對(duì)進(jìn)程進(jìn)行排序。在我們的教程中,我們按 %MEM 排序。我們可以使用Linux的sort命令來做到這一點(diǎn)。 %MEM 是第二列。

就像索引為零的數(shù)組一樣,第二個(gè)元素通過索引鍵 1 訪問。我們可以使用 sort -k 1。它按從最低到最高的順序排序。我們實(shí)際上關(guān)心的是首先消耗大量內(nèi)存的進(jìn)程。為此,我們應(yīng)該使用 sort -k 1 -r 反轉(zhuǎn)順序。一旦我們得到結(jié)果,我們可能只需要前30個(gè)過程。當(dāng)然,這取決于您,因?yàn)槟梢赃x擇包含所有內(nèi)容,但我想保持簡短。 30 聽起來是一個(gè)合理的數(shù)字。

最后,我們使用 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
一旦我們得到結(jié)果,我們將它分成一個(gè)數(shù)組并使用 foreach 循環(huán)它。我們將同名進(jìn)程分組到一個(gè)元素中,并將 CPU 百分比和內(nèi)存添加到其中。
<?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 從兩個(gè)數(shù)組創(chuàng)建一個(gè)關(guān)聯(lián)數(shù)組:一個(gè)用于鍵,一個(gè)用于值。

剩下的就是實(shí)現(xiàn) get_content 方法。只是提醒我們必須實(shí)現(xiàn)三個(gè)方法: get_title, get_metric get_content.對(duì)于這個(gè)過程,我們只想展示一個(gè)簡單的表格。

我們的 get_content 方法很簡單。

  public function get_content() {
    $processes = $this->get_metric();
    $html = '<table class="wp-list-table widefat"><thead><tr>
      <th>User</th>
      <th>Pid</th>
      <th>%CPU</th>
      <th>%Mem</th>
      <th>Command</th>
      </tr></thead><tbody>';
    foreach ($processes as $process) {
      $html .= "<tr>
        <td>{$process['user']}</td>
        <td>{$process['pid']}</td>
        <td>{$process['%cpu']}</td>
        <td>{$process['%mem']}</td>
        <td>{$process['command']}</td>
        </tr>";
    }
    $html .= '</tbody></table>';
    echo $html;
  }
這是我們得到的結(jié)果:

將Transforming a WordPress Server Dashboard into a Widget

平均負(fù)載

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

<?php
namespace AX\StatBoard\Widget;

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 來統(tǒng)計(jì) CPU 核心數(shù),并統(tǒng)計(jì)包含“processor”一詞的行數(shù)。我們?cè)?i>服務(wù)器信息

部分對(duì)此進(jìn)行了介紹。

在Linux中,/proc/loadavg保存平均負(fù)載信息。前三列分別是1分鐘、5分鐘和15分鐘的負(fù)載。 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
將上面的結(jié)果用空格分割,構(gòu)建一個(gè)包含三個(gè)元素的數(shù)組。計(jì)算所有核心的平均負(fù)載。因此,為了獲得結(jié)果,我們使用 array_map 循環(huán)遍歷 $loadAvg 數(shù)組,并除以我們擁有的核心數(shù)。請(qǐng)注意,我們創(chuàng)建了 2 個(gè)與 $loadAvg 長度相同的額外數(shù)組,一個(gè)用于鍵,另一個(gè)用于保存核心數(shù),以便將所有這些一一傳遞給 array_map。

get_content 的時(shí)間:

  public function get_content() {
    $metrics = $this->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=>$metric ) {
      array_push( $data, array( $metric[0], $metric[1] ) );
    }
    $data = json_encode( $data );
    echo <<<EOD
<div id="avg_load"></div>
<script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = google.visualization.arrayToDataTable($data);

        var options = {    
          hAxis: {
            titleTextStyle: {color: 'red'},
            minValue:0,
            maxValue:100
          }
        };

        var chart = new google.visualization.BarChart(document.getElementById('avg_load'));
        chart.draw(data, options);
      }
    </script>
EOD;
  }
我們使用條形圖并從數(shù)組創(chuàng)建一個(gè)數(shù)據(jù)數(shù)組,然后使用 json_encode 將其轉(zhuǎn)換為與條形圖數(shù)據(jù)格式匹配的 JavaScript 表示法數(shù)組。

例如:

[ ["Duration","% Load"], ["1 min",20], ["5 mins",11], ["15 mins",3]]
這是渲染圖表時(shí)的結(jié)果:

將Transforming a WordPress Server Dashboard into a Widget

以太網(wǎng)接口

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

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

<?php
/**
 * Adopt from https://github.com/afaqurk/linux-dash/blob/master/sh/ip.php
 *
 */
namespace AX\StatBoard\Widget;

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);
  }

}

所以小部件的標(biāo)題將是以太網(wǎng)。對(duì)于 get_metric,我們將嘗試獲取所有以太網(wǎng)接口名稱,然后獲取每個(gè)接口的 IP 地址,并將設(shè)備名稱和 IP 地址結(jié)合起來返回。

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

使用 IP 實(shí)用程序

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

這是我們?cè)诿钚猩线\(yùn)行它們時(shí)的結(jié)果:

[vagrant@vagrant-centos64 sbin]$ ip -oneline link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN \    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> 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,MULTICAST,UP,LOWER_UP> 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]$
如果 shell_exec 成功運(yùn)行,我們將繼續(xù)使用 IP 實(shí)用程序。上面的輸出被逐行分割成一個(gè)數(shù)組。
$output = trim($output, " \n");
$interfaces = explode("\n", $output);
然后我們循環(huán)遍歷該數(shù)組,并再次使用 ip 命令 ip -oneline -family inet addr show device_name 來獲取分配給設(shè)備的 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 地址出現(xiàn)在第四列中,因此 awk 用于打印該值。然后我們使用 cut 將命令按 / 分割,并使用 swich -f1 獲取第一個(gè)元素。

查看輸出,看看當(dāng)我們?cè)诿钚猩线\(yùn)行它們時(shí),它們是如何工作的:

[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]$
當(dāng)我們?cè)诮涌跀?shù)組中獲取設(shè)備名稱并在地址數(shù)組中獲取 IP 地址時(shí),我們創(chuàng)建一個(gè)關(guān)聯(lián)數(shù)組,其中接口名稱作為鍵,IP 地址作為值。
return array_combine($interfaces, $addreses);

使用 ifconfig 的服務(wù)器

在 ifconfig 的情況下,ipshell_exec 將返回 false。在這種情況下,我們改為運(yùn)行 ifconfig。

我們上面介紹的邏輯完全相同 - 它只是獲取信息的不同實(shí)用程序。
    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);
    }
讓我們?cè)诮K端中運(yùn)行上面的命令,以便我們了解發(fā)生了什么。

請(qǐng)注意,ifconfig 直接在輸出中顯示 IP 地址,因此我們可以直接獲取它們,而不是在設(shè)備數(shù)組上運(yùn)行循環(huán)并獲取每個(gè)設(shè)備的 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]$
一旦我們有了數(shù)據(jù),將它們放入 get_content 中就很容易了,因?yàn)槲覀冊(cè)谶@里只顯示了一個(gè)簡單的表格。

  public function get_content() {
    $interfaces = $this->get_metric();
    $html = '<table class="wp-list-table widefat"><thead><tr>
      <th>Interface</th>
      <th>IP</th>
      </tr></thead><tbody>';
    foreach ( $interfaces as $interface => $ip ) {
      $html .= "<tr>
        <td>{$interface}</td>
        <td>{$ip}</td>
        </tr>";
    }
    $html .= '</tbody></table>';
    echo $html;
  }
以下是它向管理員顯示的方式:

將Transforming a WordPress Server Dashboard into a Widget

網(wǎng)絡(luò)流量

網(wǎng)絡(luò)流量或網(wǎng)絡(luò) IO 顯示通過計(jì)算機(jī)網(wǎng)絡(luò)傳輸包的狀態(tài)。該信息是從 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
讓我們?cè)谖募?widget/networkio.php 中獲取我們的基本類 Networkio

<?php
/**
 * Adopt from https://github.com/afaqurk/linux-dash/blob/master/sh/ip.php
 *
 */
namespace AX\StatBoard\Widget;

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;  }}

我將在本文后面解釋它們。現(xiàn)在,讓我們嘗試評(píng)估我們?cè)谏厦娲a中使用的命令。

我將嘗試運(yùn)行多個(gè)命令,以便在我們將結(jié)果傳遞到另一個(gè)管道后您可以理解其中的差異。

[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 的行(前兩行),我們只關(guān)心最后三行是我們的以太網(wǎng)設(shè)備及其包傳輸。 awk 用于打印出第一、四、八列的數(shù)據(jù),分別表示接口名稱、RX-OK、TX-OK。

在我們的get_metric中,我們將結(jié)果逐行拆分到一個(gè)數(shù)組中。因?yàn)槊恳恍卸及枚禾?hào)分隔的數(shù)據(jù),所以它們被再次分割成一個(gè)數(shù)組。

我們確保只接受具有三個(gè)元素的數(shù)組。我們還嘗試將數(shù)字字符串轉(zhuǎn)換為整數(shù)值。數(shù)據(jù)將依次輸入 get_content。

  public function get_content() {
    $interfaces = $this->get_metric();
    $data = array_merge(array(array('Interface', 'Receive(package)', 'Transfer(package)')), $interfaces);
    $data = json_encode($data); 
    echo <<<EOD
      <div id="nio_chart"></div>
      <script type="text/javascript">
      google.setOnLoadCallback(function () {
        var data = google.visualization.arrayToDataTable({$data});

        var options = {
        };

        var chart = new google.visualization.ColumnChart(document.getElementById('nio_chart'));
        chart.draw(data, options);
      })        
    </script>
EOD;

  }
我們之前使用了條形圖,并嘗試將指標(biāo)數(shù)據(jù)數(shù)組格式化為條形圖數(shù)據(jù)格式,然后進(jìn)行渲染。

數(shù)據(jù)數(shù)組的每一行代表一個(gè)組條形圖,其中包含條形圖名稱及其相應(yīng)的值。在我們的例子中,每一行都是接口名稱以及 RX 欄和 TX 欄。

這是我們得到的:

將Transforming a WordPress Server Dashboard into a Widget

輸入/輸出統(tǒng)計(jì)

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

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

為了繼續(xù)執(zhí)行此操作,請(qǐng)確保系統(tǒng)上有 sysstat 軟件包。

  1. 對(duì)于 Arch Linux,使用 pacman -S sysstat 安裝 </p><p> </li> <li>對(duì)于 Debian/Ubuntu,您可以使用 <code class="inline">apt-get install sysstat 獲取它們

  2. 對(duì)于 Fedora/Centos,您可以使用 yum install sysstat
  3. 對(duì)于其他發(fā)行版,:請(qǐng)使用您的發(fā)行版包管理器進(jìn)行安裝

安裝完成后,讓我們?cè)u(píng)估一下我們將使用的一些命令。首先是第一件事:

[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狀態(tài)數(shù)據(jù)。我們對(duì)第四列中的 iowait 值感興趣。從第七行開始的數(shù)據(jù)包含硬盤驅(qū)動(dòng)器每秒的讀/寫塊。

如果您有許多硬盤連接到服務(wù)器,您將擁有多個(gè)設(shè)備:sdb、sdc 等。

數(shù)據(jù)是塊的數(shù)量,而不是實(shí)際大?。ㄒ哉鬃止?jié)為單位)。我們必須找到塊大小來計(jì)算總大小。

塊大小存儲(chǔ)在/sys/block/sda/queue/physical_block_size中。

[vagrant@vagrant-centos64 ~]$ cat /sys/block/sda/queue/physical_block_size
512
[vagrant@vagrant-centos64 ~]$
所以我的sda的塊大小是512。我們將每秒讀取的塊數(shù)與塊大小相乘,得到讀/寫數(shù)據(jù)的實(shí)際大小。

有了上面的基本知識(shí),讓我們?cè)?widget/iostat.php 中創(chuàng)建我們的類 Iostat 。

<?php

namespace AX\StatBoard\Widget;

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'  => floatval($avg_cpu[2]) * $number_of_core,
      'io_wait' => floatval($avg_cpu[3]) * $number_of_core,
      'other'   => 100 - ($avg_cpu[0] + $avg_cpu[2] + $avg_cpu[3])
    );
    
    if (sizeof($lines) >=7) {
      for ($i=6,$l = sizeof($lines);$i<$l; $i++) {
        $line = preg_split("/\s+/", $lines[$i]);
        if (!is_array($line) || sizeof($line)<5) {
          continue;
        }
        // Calculate block size
        $block_size = shell_exec("cat /sys/block/{$lines[1]}/queue/physical_block_size");

        $metric['disk'][$line[0]] = array(
          'read'  => floatval($line[2]) * $block_size / 1024,
          'write' => floatval($line[3]) * $block_size / 1024,
        );

      }  
    }

    return $metric;
  }

}

我們只是嘗試將我們的理論應(yīng)用到 PHP 代碼中。獲取 iostat 的輸出,將其轉(zhuǎn)換為數(shù)組,每一行都是一個(gè)元素。

第四行被空格分割并映射到關(guān)聯(lián)數(shù)組中。第七行之后的所有行都放入另一個(gè)關(guān)聯(lián)數(shù)組中,其中鍵是設(shè)備名稱(sda,sdb,sdc,..),如果以兆字節(jié)為單位讀取和寫入,則值是一個(gè)數(shù)組。

一旦我們獲得了指標(biāo),將其輸入 get_content 并渲染我們的圖表。

  public function get_content() {
    $metric = $this->get_metric();
    $disk_io = array(
      array('Disk', 'Read(MB)', 'Write(MB)'),
    );
    foreach ($metric['disk'] as $disk=>$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
      <div id="widget_disk_io"></div>
      <div id="widget_cpu_io_wait"></div>
      <script type="text/javascript">
      google.load('visualization', '1', {packages:['gauge']});
      google.setOnLoadCallback(function () {
        var data = google.visualization.arrayToDataTable({$cpu_io});
        var goptions = {
          redFrom: 80, redTo: 100,
          yellowFrom:50, yellowTo: 80,
          minorTicks: 5
        };
        var chart = new google.visualization.Gauge(document.getElementById('widget_cpu_io_wait'));
        chart.draw(data, goptions);

        var data2 = google.visualization.arrayToDataTable({$disk_io});
        var chart2 = new google.visualization.ColumnChart(document.getElementById('widget_disk_io'));
        chart2.draw(data2, {});
      })        
    </script>
EOD;

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

將Transforming a WordPress Server Dashboard into a Widget

The above is the detailed content of 將Transforming a WordPress Server Dashboard into a Widget. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to revert WordPress core update How to revert WordPress core update Jul 02, 2025 am 12:05 AM

To roll back the WordPress version, you can use the plug-in or manually replace the core file and disable automatic updates. 1. Use WPDowngrade and other plug-ins to enter the target version number to automatically download and replace; 2. Manually download the old version of WordPress and replace wp-includes, wp-admin and other files through FTP, but retain wp-config.php and wp-content; 3. Add code in wp-config.php or use filters to disable core automatic updates to prevent further upgrades. Be sure to back up the website and database before operation to ensure safety and reliability. It is recommended to keep the latest version for security and functional support in the long term.

How to create a custom shortcode in WordPress How to create a custom shortcode in WordPress Jul 02, 2025 am 12:21 AM

The steps to create a custom shortcode in WordPress are as follows: 1. Write a PHP function through functions.php file or custom plug-in; 2. Use add_shortcode() to bind the function to the shortcode tag; 3. Process parameters in the function and return the output content. For example, when creating button shortcodes, you can define color and link parameters for flexible configuration. When using it, you can insert a tag like [buttoncolor="red"url="https://example.com"] in the editor, and you can use do_shortcode() to model it

How to diagnose high CPU usage caused by WordPress How to diagnose high CPU usage caused by WordPress Jul 06, 2025 am 12:08 AM

The main reasons why WordPress causes the surge in server CPU usage include plug-in problems, inefficient database query, poor quality of theme code, or surge in traffic. 1. First, confirm whether it is a high load caused by WordPress through top, htop or control panel tools; 2. Enter troubleshooting mode to gradually enable plug-ins to troubleshoot performance bottlenecks, use QueryMonitor to analyze the plug-in execution and delete or replace inefficient plug-ins; 3. Install cache plug-ins, clean up redundant data, analyze slow query logs to optimize the database; 4. Check whether the topic has problems such as overloading content, complex queries, or lack of caching mechanisms. It is recommended to use standard topic tests to compare and optimize the code logic. Follow the above steps to check and solve the location and solve the problem one by one.

How to optimize WordPress without plugins How to optimize WordPress without plugins Jul 05, 2025 am 12:01 AM

Methods to optimize WordPress sites that do not rely on plug-ins include: 1. Use lightweight themes, such as Astra or GeneratePress, to avoid pile-up themes; 2. Manually compress and merge CSS and JS files to reduce HTTP requests; 3. Optimize images before uploading, use WebP format and control file size; 4. Configure.htaccess to enable browser cache, and connect to CDN to improve static resource loading speed; 5. Limit article revisions and regularly clean database redundant data.

How to minify JavaScript files in WordPress How to minify JavaScript files in WordPress Jul 07, 2025 am 01:11 AM

Miniving JavaScript files can improve WordPress website loading speed by removing blanks, comments, and useless code. 1. Use cache plug-ins that support merge compression, such as W3TotalCache, enable and select compression mode in the "Minify" option; 2. Use a dedicated compression plug-in such as FastVelocityMinify to provide more granular control; 3. Manually compress JS files and upload them through FTP, suitable for users familiar with development tools. Note that some themes or plug-in scripts may conflict with the compression function, and you need to thoroughly test the website functions after activation.

How to use the Transients API for caching How to use the Transients API for caching Jul 05, 2025 am 12:05 AM

TransientsAPI is a built-in tool in WordPress for temporarily storing automatic expiration data. Its core functions are set_transient, get_transient and delete_transient. Compared with OptionsAPI, transients supports setting time of survival (TTL), which is suitable for scenarios such as cache API request results and complex computing data. When using it, you need to pay attention to the uniqueness of key naming and namespace, cache "lazy deletion" mechanism, and the issue that may not last in the object cache environment. Typical application scenarios include reducing external request frequency, controlling code execution rhythm, and improving page loading performance.

How to use object caching for persistent storage How to use object caching for persistent storage Jul 03, 2025 am 12:23 AM

Object cache assists persistent storage, suitable for high access and low updates, tolerating short-term lost data. 1. Data suitable for "persistence" in cache includes user configuration, popular product information, etc., which can be restored from the database but can be accelerated by using cache. 2. Select a cache backend that supports persistence such as Redis, enable RDB or AOF mode, and configure a reasonable expiration policy, but it cannot replace the main database. 3. Set long TTL or never expired keys, adopt clear key name structure such as user:1001:profile, and update the cache synchronously when modifying data. 4. It can combine local and distributed caches to store small data locally and big data Redis to store big data and use it for recovery after restart, while paying attention to consistency and resource usage issues.

How to prevent comment spam programmatically How to prevent comment spam programmatically Jul 08, 2025 am 12:04 AM

The most effective way to prevent comment spam is to automatically identify and intercept it through programmatic means. 1. Use verification code mechanisms (such as Googler CAPTCHA or hCaptcha) to effectively distinguish between humans and robots, especially suitable for public websites; 2. Set hidden fields (Honeypot technology), and use robots to automatically fill in features to identify spam comments without affecting user experience; 3. Check the blacklist of comment content keywords, filter spam information through sensitive word matching, and pay attention to avoid misjudgment; 4. Judge the frequency and source IP of comments, limit the number of submissions per unit time and establish a blacklist; 5. Use third-party anti-spam services (such as Akismet, Cloudflare) to improve identification accuracy. Can be based on the website

See all articles