將 WordPress 伺服器儀表板轉(zhuǎn)變?yōu)樾」ぞ?/h1> Sep 03, 2023 pm 09:13 PM
回想一下,所有小部件提供程序都必須實(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è)字段
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 使用情況。
get_metric()
來(lái)獲取必要的數(shù)據(jù)。然后,我們只需循環(huán)它并格式化它以匹配 Google 圖表數(shù)據(jù)要求。最后,我們使用 json_encode
將它們轉(zhuǎn)換為 JavaScript 對(duì)象表示法(或 JSON)。然后,我們輸出一個(gè) HTML 代碼,其中包含 div
元素來(lái)保存圖表對(duì)象。 div
元素中。安裝的軟件
我們將介紹的第二個(gè)小部件是顯示已安裝軟件的小部件。它是一個(gè)小部件,旨在顯示我們?cè)诜?wù)器上有哪些常見(jiàn)軟件包以及哪個(gè)版本。
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()
,我們想知道是否安裝了特定的軟件。如果有,則獲取其版本信息。 php -v
顯示版本信息,mysql --version
顯示MySQL信息。 shell_exec
將返回 false
。此時(shí),我們可以判斷該軟件沒(méi)有安裝;否則,我們可以解析結(jié)果以顯示版本信息。然后,我們逐行分割結(jié)果,并檢索第一行作為版本信息。這是因?yàn)槲覀冃枰男畔⒅荒茉诘谝恍姓业健?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í)的儀表板:
磁盤使用情況
現(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è)圖表:
- 第一個(gè)圖表顯示了每個(gè)已安裝文件系統(tǒng)的總空間。對(duì)于此數(shù)據(jù),我們將使用餅圖。
- 第二個(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ù)格式。
服務(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
<?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
類來(lái)自全局命名空間。每次我們想要使用 DateTime
時(shí),我們都必須輸入 \DateTime
。因此,我們使用命名空間導(dǎo)入來(lái)使 DateTime
名稱在我們當(dāng)前的命名空間中可用。 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; }這是儀表板上的小部件。
處理器
監(jiān)控我們的處理器是其中之一我們可以展示的最重要的東西。我們想知道某個(gè)特定進(jìn)程正在使用多少 CPU 和/或消耗了多少內(nèi)存。我們將我們的類稱為Process
,首先從 get_title
和 get_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)。 -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
是第二列。 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ù)字。 [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è)用于值。 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é)果:
平均負(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)行了介紹。
/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é)果:
以太網(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)返回。 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
將 : 替換為空字符串。
[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è)元素。
[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 的情況下,ip
的 shell_exec
將返回 false
。在這種情況下,我們改為運(yùn)行 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); }讓我們?cè)诮K端中運(yùn)行上面的命令,以便我們了解發(fā)生了什么。
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; }以下是它向管理員顯示的方式:
網(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中使用的命令。
[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)排除包含單詞 Iface 或 Kernel 的行(前兩行),我們只關(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ù)組。
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)行渲染。
輸入/輸出統(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 軟件包。
- 對(duì)于 Arch Linux,使用 pacman -S sysstat 安裝
</p><p> </li> <li>對(duì)于 Debian/Ubuntu,您可以使用 <code class="inline">apt-get install sysstat
獲取它們 - 對(duì)于 Fedora/Centos,您可以使用
yum install sysstat
- 對(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)器每秒的讀/寫塊。 [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è)元素。 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)重事件,并用紅色突出顯示。
以上是將 WordPress 伺服器儀表板轉(zhuǎn)變?yōu)樾」ぞ叩脑敿?xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

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

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

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

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

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

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

要回滾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)建自定義短代碼的步驟如下: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導(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)化代碼邏輯。按照上述步驟逐一排查可定位並解

優(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ù)。

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)站功能。

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ì)象緩存可輔助持久存儲(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)論垃圾信息最有效的方式是通過(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)站
