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

目錄
RAM 使用情況小部件
磁盤使用情況
服務(wù)器信息
主機(jī)名
名稱-sr
grep -c ^處理器/proc/cpuinfo
CPU型號(hào)
處理器
以太網(wǎng)接口
使用 ifconfig 的服務(wù)器
網(wǎng)絡(luò)流量
輸入/輸出統(tǒng)計(jì)
首頁(yè) CMS教程 &#&按 將 WordPress 伺服器儀表板轉(zhuǎn)變?yōu)樾」ぞ?/span>

將 WordPress 伺服器儀表板轉(zhuǎn)變?yōu)樾」ぞ?/h1> Sep 03, 2023 pm 09:13 PM


將Transforming a WordPress Server Dashboard into a Widget

在上一篇文章中,我們創(chuàng)建了插件的基本結(jié)構(gòu)?,F(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 開(kāi)關(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";
  }

?>
接下來(lái),我們將實(shí)現(xiàn) get_metric 來(lái)實(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}' .它的輸出看起來(lái)與此類似。

[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 ~]$
我們通過(guò)將行拆分為數(shù)組來(lái)使用 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;
  }
我們使用堆積條形圖來(lái)顯示 RAM 使用情況。

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

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

將Transforming a WordPress Server Dashboard into a Widget

安裝的軟件

我們將介紹的第二個(gè)小部件是顯示已安裝軟件的小部件。它是一個(gè)小部件,旨在顯示我們?cè)诜?wù)器上有哪些常見(jiàn)軟件包以及哪個(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è)簡(jiǎn)單的字符串。對(duì)于 get_metric(),我們想知道是否安裝了特定的軟件。如果有,則獲取其版本信息。

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

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

對(duì)于其他應(yīng)用程序,某些命令過(guò)于冗長(zhǎ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è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)題。接下來(lái)是我們課程的核心:獲取磁盤使用情況的方法。

<?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ù)組來(lái)匹配圖表數(shù)據(jù)格式要求。數(shù)據(jù)數(shù)組應(yīng)如下所示:

[  ['File System', 'Free', 'Used',
  ['/dev/sda1', 10, 24],
  ['/dev/sda2', 28, 19]]
一旦我們有了數(shù)據(jù),我們就開(kāi)始渲染圖表。我們將制作兩個(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 元素來(lái)包含信息
      <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è)簡(jiǎn)單的數(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)題。

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

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

主機(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 開(kāi)關(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)直接訪問(wèn)時(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 開(kāi)始。我將在代碼后面解釋 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ò)開(kāi)關(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。如果您嘗試該命令,您將得到一些奇怪的過(guò)程,例如:

[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]?;旧希@意味著該命令無(wú)法在文件系統(tǒng)中找到。它可能是一些內(nèi)部系統(tǒng)進(jìn)程或內(nèi)核線程,我們可能永遠(yuǎn)不想關(guān)心它。因此,我們應(yīng)該使用 grep 來(lái)消除這些進(jìn)程。 grep 有 -v 開(kāi)關(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ù)看起來(lái)不錯(cuò),我們應(yīng)該按內(nèi)存或CPU對(duì)進(jìn)程進(jìn)行排序。在我們的教程中,我們按 %MEM 排序。我們可以使用Linux的sort命令來(lái)做到這一點(diǎn)。 %MEM 是第二列。

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

最后,我們使用 awk 來(lái)格式化輸出。這是我們的命令和示例輸出:

[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è)過(guò)程,我們只想展示一個(gè)簡(jiǎn)單的表格。

我們的 get_content 方法很簡(jiǎn)單。

  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è)命令可以顯示過(guò)去一分鐘、五分鐘和 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)      );  }

}
首先,我們通過(guò)讀取 /proc/cpuinfo 來(lái)統(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 在這里用于過(guò)濾掉我們需要的字段。
?  ~  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 長(zhǎng)度相同的額外數(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)容開(kā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é)合起來(lái)返回。

我們需要處理兩種情況:如果服務(wù)器使用 ifconfig 或服務(wù)器使用 ip 實(shí)用程序。較新的服務(wù)器很可能有 ip 而不是 ifconfig;?因此,我們應(yīng)該首先運(yùn)行 ip 來(lái)獲取以太網(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 來(lái)獲取分配給設(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è)簡(jiǎn)單的表格。

  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 顯示通過(guò)計(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 來(lái)排除包含單詞 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ì)空閑下來(lái)等待結(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 值感興趣。從第七行開(kāi)始的數(shù)據(jù)包含硬盤驅(qū)動(dòng)器每秒的讀/寫塊。

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

數(shù)據(jù)是塊的數(shù)量,而不是實(shí)際大?。ㄒ哉鬃止?jié)為單位)。我們必須找到塊大小來(lái)計(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 等待,我們使用儀表圖來(lái)使其看起來(lái)更漂亮。我們認(rèn)為 80-100 的 IOwait 是一個(gè)嚴(yán)重事件,并用紅色突出顯示。

將Transforming a WordPress Server Dashboard into a Widget

以上是將 WordPress 伺服器儀表板轉(zhuǎn)變?yōu)樾」ぞ叩脑敿?xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

如何恢復(fù)WordPress核心更新 如何恢復(fù)WordPress核心更新 Jul 02, 2025 am 12:05 AM

要回滾WordPress版本,可使用插件或手動(dòng)替換核心文件,並禁用自動(dòng)更新。 1.使用WPDowngrade等插件輸入目標(biāo)版本號(hào)即可自動(dòng)下載替換;2.手動(dòng)下載舊版WordPress並通過(guò)FTP替換wp-includes、wp-admin等文件但保留wp-config.php和wp-content;3.在wp-config.php中添加代碼或使用過(guò)濾器禁用核心自動(dòng)更新以防止再次升級(jí)。操作前務(wù)必備份網(wǎng)站和數(shù)據(jù)庫(kù),確保安全可靠。長(zhǎng)期建議保持最新版以保障安全性與功能支持。

如何在WordPress中創(chuàng)建自定義短代碼 如何在WordPress中創(chuàng)建自定義短代碼 Jul 02, 2025 am 12:21 AM

在WordPress中創(chuàng)建自定義短代碼的步驟如下:1.通過(guò)functions.php文件或自定義插件編寫PHP函數(shù);2.使用add_shortcode()將函數(shù)綁定到短代碼標(biāo)籤;3.在函數(shù)中處理參數(shù)並返回輸出內(nèi)容。例如,創(chuàng)建按鈕短代碼時(shí)可定義顏色和鏈接參數(shù),實(shí)現(xiàn)靈活配置。使用時(shí)可在編輯器中插入類似[buttoncolor="red"url="https://example.com"]點(diǎn)擊這裡[/button]的標(biāo)籤,並可通過(guò)do_shortcode()在模

如何診斷WordPress引起的高CPU使用 如何診斷WordPress引起的高CPU使用 Jul 06, 2025 am 12:08 AM

WordPress導(dǎo)致服務(wù)器CPU使用率飆升的主要原因包括插件問(wèn)題、數(shù)據(jù)庫(kù)查詢效率低、主題代碼質(zhì)量差或流量激增。 1.首先通過(guò)top、htop或控制面板工具確認(rèn)是否為WordPress引起的高負(fù)載;2.進(jìn)入故障排查模式逐步啟用插件排查性能瓶頸,使用QueryMonitor分析插件執(zhí)行情況並刪除或替換低效插件;3.安裝緩存插件、清理冗餘數(shù)據(jù)、分析慢查詢?nèi)照I以優(yōu)化數(shù)據(jù)庫(kù);4.檢查主題是否存在過(guò)度加載內(nèi)容、複雜查詢或缺乏緩存機(jī)制等問(wèn)題,建議用標(biāo)準(zhǔn)主題測(cè)試對(duì)比並優(yōu)化代碼邏輯。按照上述步驟逐一排查可定位並解

如何在沒(méi)有插件的情況下優(yōu)化WordPress 如何在沒(méi)有插件的情況下優(yōu)化WordPress Jul 05, 2025 am 12:01 AM

優(yōu)化WordPress站點(diǎn)不依賴插件的方法包括:1.使用輕量級(jí)主題,如Astra或GeneratePress,避免功能堆砌的主題;2.手動(dòng)壓縮和合併CSS、JS文件,減少HTTP請(qǐng)求;3.上傳前優(yōu)化圖片,使用WebP格式並控製文件大?。?.配置.htaccess啟用瀏覽器緩存,並接入CDN提升靜態(tài)資源加載速度;5.限製文章修訂版本並定期清理數(shù)據(jù)庫(kù)冗餘數(shù)據(jù)。

如何在WordPress中縮小JavaScript文件 如何在WordPress中縮小JavaScript文件 Jul 07, 2025 am 01:11 AM

MinifyingJavaScript文件可通過(guò)刪除空白、註釋和無(wú)用代碼來(lái)提升WordPress網(wǎng)站加載速度。 1.使用支持合併壓縮的緩存插件如W3TotalCache,在“Minify”選項(xiàng)中啟用並選擇壓縮模式;2.使用專用壓縮插件如FastVelocityMinify,提供更精細(xì)控制;3.手動(dòng)壓縮JS文件並通過(guò)FTP上傳,適用於熟悉開(kāi)發(fā)工具的用戶。注意部分主題或插件腳本可能與壓縮功能衝突,啟用後需徹底測(cè)試網(wǎng)站功能。

如何使用瞬態(tài)API進(jìn)行緩存 如何使用瞬態(tài)API進(jìn)行緩存 Jul 05, 2025 am 12:05 AM

TransientsAPI是WordPress中用於臨時(shí)存儲(chǔ)可自動(dòng)過(guò)期數(shù)據(jù)的內(nèi)置工具,其核心函數(shù)為set_transient、get_transient和delete_transient。相比OptionsAPI,transients支持設(shè)置生存時(shí)間(TTL),適合緩存API請(qǐng)求結(jié)果、複雜計(jì)算數(shù)據(jù)等場(chǎng)景。使用時(shí)需注意key命名唯一性與命名空間、緩存“懶刪除”機(jī)制及對(duì)象緩存環(huán)境下可能不持久的問(wèn)題。典型應(yīng)用場(chǎng)景包括減少外部請(qǐng)求頻率、控制代碼執(zhí)行節(jié)奏和提升頁(yè)面加載性能。

如何使用對(duì)象緩存進(jìn)行持續(xù)存儲(chǔ) 如何使用對(duì)象緩存進(jìn)行持續(xù)存儲(chǔ) Jul 03, 2025 am 12:23 AM

對(duì)象緩存可輔助持久存儲(chǔ),適用於高訪問(wèn)低更新、可容忍短暫丟失的數(shù)據(jù)。 1.適合用緩存“持久化”的數(shù)據(jù)包括用戶配置、熱門商品信息等,能從數(shù)據(jù)庫(kù)恢復(fù)但使用緩存可加速訪問(wèn)。 2.選擇Redis等支持持久化的緩存後端,啟用RDB或AOF模式,並配置合理過(guò)期策略,但不能替代主數(shù)據(jù)庫(kù)。 3.設(shè)置長(zhǎng)TTL或永不過(guò)期鍵,採(cǎi)用清晰鍵名結(jié)構(gòu)如user:1001:profile,修改數(shù)據(jù)時(shí)同步更新緩存。 4.可結(jié)合本地與分佈式緩存,本地存小數(shù)據(jù)、Redis存大數(shù)據(jù)並用於重啟後恢復(fù),同時(shí)注意一致性與資源佔(zhàn)用問(wèn)題。

如何以編程方式防止評(píng)論垃圾郵件 如何以編程方式防止評(píng)論垃圾郵件 Jul 08, 2025 am 12:04 AM

防止評(píng)論垃圾信息最有效的方式是通過(guò)程序化手段自動(dòng)識(shí)別並攔截。 1.使用驗(yàn)證碼機(jī)制(如GooglereCAPTCHA或hCaptcha)可有效區(qū)分人類與機(jī)器人,尤其適合公眾網(wǎng)站;2.設(shè)置隱藏字段(Honeypot技術(shù)),利用機(jī)器人自動(dòng)填寫特性識(shí)別垃圾評(píng)論,不影響用戶體驗(yàn);3.檢查評(píng)論內(nèi)容關(guān)鍵詞黑名單,通過(guò)敏感詞匹配過(guò)濾垃圾信息,需注意避免誤判;4.判斷評(píng)論頻率與來(lái)源IP,限制單位時(shí)間內(nèi)的提交次數(shù)並建立黑名單;5.使用第三方反垃圾服務(wù)(如Akismet、Cloudflare)提升識(shí)別準(zhǔn)確性??筛鶕?jù)網(wǎng)站

See all articles