### [将Transforming a WordPress Server Dashboard into a Widget](https://www.prosaas.cn/article/4561) **Published:** 2023-09-03T13:13:12 **Author:** 5201314 **Excerpt:** 在上一篇文章中,我们创建了插件的基本结构。现在是时候为每个小部件实现渲染类了。回想一下,所有小部件提供程序都必… ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123053471.png) 在上一篇文章中,我们创建了插件的基本结构。现在是时候为每个小部件实现渲染类了。 回想一下,所有小部件提供程序都必须实现 `Provider` 接口。它们还必须位于名为 `widget` 的文件夹内,并位于名称空间 `AX\StatBoard\Widget` 下。如果我们想添加一种新的指标,只需创建一个相应的类,并创建一个对象并使用 `add_provider` 方法将其添加到 `Widget` 类中。 ## RAM 使用情况小部件 我们想要显示的第一条信息是当前正在使用的 RAM 量以及当前空闲的 RAM 量。 在本例中,`free -m` 是我们的朋友 - 它告诉我们 RAM 使用情况。 `-m` 开关是以兆字节为单位输出结果。 \[vagrant@vagrant-centos64 ~\]$ free -m total used free shared buffers cached Mem: 589 366 223 0 9 57 -/+ buffers/cache: 299 290 Swap: 0 0 0 我们将类命名为 `Ram`。相应的文件将为 `widget/ram.php`。我们在这里只是编写基础并实现 `get_title` 。 接下来,我们将实现 `get_metric` 来实际运行必要的 shell 命令并提取信息。稍后我将解释 `get_metric` 的更多细节。 trim( $segment\[0\]," :" ), 'total' => (int)$segment\[1\], 'used' => (int)$segment\[2\], 'free' => (int)$segment\[3\], ); }, $df ); return $df; } return false; } ?> 我们执行命令 `free -m | grep -E "内存|交换" | awk '{print $1, $2, $3, $4}' `.它的输出看起来与此类似。 \[vagrant@vagrant-centos64 ~\]$ free -m | grep -E "Mem|Swap" | awk '{print $1, $2, $3, $4}' Mem: 589 541 47 Swap: 255 0 255 \[vagrant@vagrant-centos64 ~\]$ 我们通过将行拆分为数组来使用 PHP 解析每一位信息。我们使用 `array_map` 循环遍历数组的所有元素,对于每一行,我们用空格分隔,然后返回一个包含元素的_关联_数组: - `type`:第一个字段 - `total`:第二个字段 - `used`:第三个字段 - `free`:第四个字段 现在,是 `get_content` 的时候了。 public function get\_content() { $metric = $this->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; } 我们使用堆积条形图来显示 RAM 使用情况。 首先,我们调用 `get_metric()` 来获取必要的数据。然后,我们只需循环它并格式化它以匹配 Google 图表数据要求。最后,我们使用 `json_encode` 将它们转换为 JavaScript 对象表示法(或 JSON)。然后,我们输出一个 HTML 代码,其中包含 `div` 元素来保存图表对象。 最后,我们调用相应的 Google Chart API 将图表渲染到 `div` 元素中。 ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123053666.jpg) ## 安装的软件 我们将介绍的第二个小部件是显示已安装软件的小部件。它是一个小部件,旨在显示我们在服务器上有哪些常见软件包以及哪个版本。 例如,我们是否安装了 NodeJS,是否安装了 Ruby?我们使用的是哪个版本的 PHP?等等。 让我们使用以下初始内容创建 `widget/software.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 \] .= '
' . $version; } return $cmds; } 因此,与往常一样,我们有 `get_title` ,它只返回一个简单的字符串。对于 `get_metric()`,我们想知道是否安装了特定的软件。如果有,则获取其版本信息。 为此,我们使用显示软件版本的开关创建一个命令数组。以PHP为例,`php -v` 显示版本信息,`mysql --version` 显示MySQL信息。 如果命令返回且错误或未找到命令,则 `shell_exec` 将返回 `false`。此时,我们可以判断该软件没有安装;否则,我们可以解析结果以显示版本信息。然后,我们逐行分割结果,并检索第一行作为版本信息。这是因为我们需要的信息只能在第一行找到。 对于其他应用程序,某些命令过于冗长,包含许多信息。一旦我们有了数据,就可以创建 `get_content` 方法了。 public function get\_content() { $cmds = $this->get\_metric(); $content = ''; foreach ( $cmds as $cmd => $info ) { $content .= "

$cmd  $info

"; } echo $content; } 我们只是展示此类数据的基本表格。这是显示时的仪表板: ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123053138.jpg) ### 磁盘使用情况 现在我们将解决磁盘使用问题。我们将处理此任务的类命名为 `Disk`。让我们先制作基本骨架。 =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; } 在本系列的第一部分中,我们对 `df` 命令有了一些了解,因此理解以下命令应该很容易: 回想一下 `df` 输出: \[vagrant@vagrant-centos64 ~\]$ df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 7.3G 1.4G 5.6G 20% / tmpfs 295M 0 295M 0% /dev/shm /vagrant 60G 55G 4.9G 92% /vagrant /data/GeoIP 60G 55G 4.9G 92% /data/GeoIP /var/webapps 60G 55G 4.9G 92% /var/webapps /var/www/html 60G 55G 4.9G 92% /var/www/html 我们将其逐行拆分,将其变成数组。我们循环遍历每一行,用空格分割整行,再次将其转换为数组。然后,我们只需将值映射为更友好、人类可读的关联数组。当我们有了这些数据后,我们可以将其放入 `get_content`. public function get\_content() { $metric = $this->get\_metric(); $data = array( array( 'Disk', 'Space' ) ); $disk\_container = array(); $data\_partition = array( array('Filesystem', 'Free(GB)', 'Used(GB)') ); foreach ( $metric as $disk ) { $size = intval( $disk\['size'\] ); if ( 'M' == substr( $disk\['size'\], -1 ) ) { $size = round( $size / 1024, 2 ); } $used = intval( $disk\['used'\] ); if ('M' == substr( $disk\['used'\], -1 ) ) { $used = round( $used / 1024, 2 ); } if ( empty( $size ) ) { continue; } $data\[\] = array( $disk\['filesystem'\], $size ); $data\_partition\[\] = array($disk\['filesystem'\], $size - $used, $used); } } 我们遍历度量数组并尝试将 MB 空间转换为 GB 空间。我们构建一个数组来匹配图表数据格式要求。数据数组应如下所示: \[ \['File System', 'Free', 'Used', \['/dev/sda1', 10, 24\], \['/dev/sda2', 28, 19\]\] 一旦我们有了数据,我们就开始渲染图表。我们将制作两个图表: 1. 第一个图表显示了每个已安装文件系统的总空间。对于此数据,我们将使用饼图。 2. 第二个图表用于显示每个已安装文件系统的磁盘使用情况。为此,我们将使用条形图。 为此,我们将方法修改为以下内容: public function get\_content() { $metric = $this->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` 元素来包含信息
然后,使用图表 API 的绘制方法将图表渲染在这些元素内。这里最令人困惑的事情可能是我们图表的数据格式。 结果如下: ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123053981.jpg) ## 服务器信息 这个小部件向我们显示信息:Linux 内核、CPU 架构、正常运行时间、IP 地址。我们这里不需要图表,一个简单的数据表就可以完成这项工作。调用该类是`Server`。这是 `widget/server.php` 的第一个内容 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; } } 至此,您应该熟悉 `get_title()`。我们只是返回这个小部件的标题。 首先,我们使用语句 `use DateTime` 因为我们位于名称空间 `AX\StatBoard\Widget` 中,并且 `DateTime` 类来自全局命名空间。每次我们想要使用 `DateTime` 时,我们都必须输入 `\DateTime`。因此,我们使用命名空间导入来使 `DateTime` 名称在我们当前的命名空间中可用。 将其视为符号链接。在 `get_metric` 中,我们运行 shell 命令来获取结果并将其分配回来。 ### **主机名** 显示您的服务器主机名。 ### **名称-sr** 显示Linux内核信息: \[vagrant@vagrant-centos64 ~\]$ uname -sr Linux 2.6.32-358.23.2.el6.x86\_64 ### **grep -c ^处理器/proc/cpuinfo** \-c 开关打印输入字符串中匹配行的计数。 `/proc/cpuinfo` 包含处理器信息。我们 grep 它并计算文字处理器的出现次数。这是我的 32 核结果。 $ grep -c ^processor /proc/cpuinfo 32 ### **剪切-d。 -f1 /proc/uptime** 此命令显示服务器已启动并运行的秒数。我们将秒数转换为“x 天 y 小时 z 分钟”的格式,以使其更加用户友好。 使用 DateTime::diff 我们可以轻松实现这一点。我们创建一个带有当前时间戳的 `DateTime` 对象,另一个带有时间戳的对象是当前时间戳减去正常运行时间的秒数。然后使用 format 方法将其格式化为人类友好的字符串。 这是我的结果,正常运行时间为 26194091 秒。 $ cut -d. -f1 /proc/uptime 26194091 ### **卷曲 ifconfig.me** `ifconfig.me` 是一项在浏览器内直接访问时显示您的 IP 地址的服务。如果您使用 `curl` 向其发送请求,它将以单个字符串形式返回您的 IP 地址。 \[vagrant@vagrant-centos64 ~\]$ curl ifconfig.me 76.102.253.237 ### CPU型号 如上所述,`/proc/cpuinfo`存储了CPU信息。我们可以从中提取CPU型号。例如: \[vagrant@vagrant-centos64 ~\]$ cat /proc/cpuinfo | grep "model name" | awk '{print $4,$5,$6,$7}' Intel(R) Core(TM) i5-4250U CPU 一旦我们在数组中获得了所有可用数据,我们就会返回它并向 `get_content` 方法提供这些数据。这是 `get_content`,仅显示数据: public function get\_content() { $server = $this->get\_metric(); echo <<Ip Address {$server\['ip'\]}
CPU  {$server\['cpu'\]}
Number of Core  {$server\['core'\]}
Ram  {$server\['ram'\]}
Hostname {$server\['hostname'\]}
OS {$server\['os'\]}
Uptime {$server\['uptime'\]}
EOD; } 这是仪表板上的小部件。 ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054830.jpg) ## 处理器 监控我们的处理器是其中之一我们可以展示的最重要的东西。我们想知道某个特定进程正在使用多少 CPU 和/或消耗了多少内存。我们将我们的类称为 `Process`,首先从 `get_title` 和 `get_metric` 开始。我将在代码后面解释 `get_metric` 的更多细节: count( $line ) ) { continue; } if ( empty( $processes\[ $line\[6\] \] ) ) { $processes\[ $line\[6\]\] = array\_combine( array( 'user', 'pid', '%cpu', '%mem','start','time', 'command' ), $line ); } else { $processes\[ $line\[6\] \]\['%cpu'\] += $line\[2\]; $processes\[ $line\[6\] \]\['%mem'\] += $line\[3\]; } } //... 我们使用 `array_combine` 从两个数组创建一个关联数组:一个用于键,一个用于值。 剩下的就是实现 `get_content` 方法。只是提醒我们必须实现三个方法: `get_title`, `get_metric` 和 `get_content`.对于这个过程,我们只想展示一个简单的表格。 我们的 `get_content` 方法很简单。 public function get\_content() { $processes = $this->get\_metric(); $html = ''; foreach ($processes as $process) { $html .= ""; } $html .= '
User Pid %CPU %Mem Command
{$process\['user'\]} {$process\['pid'\]} {$process\['%cpu'\]} {$process\['%mem'\]} {$process\['command'\]}
'; echo $html; } 这是我们得到的结果: ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054294.jpg) ## 平均负载 Linux 有一个命令可以显示过去一分钟、五分钟和 15 分钟内 CPU 和 IO 的平均负载。让我们把它压缩成一个小部件。称之为 `Cpuload`,并创建我们的 `widget/cpuload.php` 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; } 我们使用条形图并从数组创建一个数据数组,然后使用 `json_encode` 将其转换为与条形图数据格式匹配的 JavaScript 表示法数组。 例如: \[ \["Duration","% Load"\], \["1 min",20\], \["5 mins",11\], \["15 mins",3\]\] 这是渲染图表时的结果: ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054170.jpg) ## 以太网接口 我们要处理的下一个小部件是以太网接口。某些服务器可以有多个以太网接口,并为其分配不同的 IP 地址。 看到这些信息非常有用。我们将这个类称为 `Ethernet`,从 `widget/ethernet.php` 的基本内容开始。 mtu 16436 qdisc noqueue state UNKNOWN \\ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: 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: 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` 成功运行,我们将继续使用 IP 实用程序。上面的输出被逐行分割成一个数组。 $output = trim($output, " \\n"); $interfaces = explode("\\n", $output); 然后我们循环遍历该数组,并再次使用 `ip` 命令 `ip -oneline -family inet addr show device_name` 来获取分配给设备的 IP 地址。 $addreses = array(); foreach ($interfaces as $interface) { $output = shell\_exec("ip -oneline -family inet addr show $interface | awk '{print $4}' | cut -d'/' -f1"); $addreses\[\] = $output; } IP 地址出现在第四列中,因此 awk 用于打印该值。然后我们使用 cut 将命令按 / 分割,并使用 swich -f1 获取第一个元素。 查看输出,看看当我们在命令行上运行它们时,它们是如何工作的: \[vagrant@vagrant-centos64 sbin\]$ ip -oneline -family inet addr show eth1 3: eth1 inet 192.168.1.111/24 brd 192.168.1.255 scope global eth1 \[vagrant@vagrant-centos64 sbin\]$ ip -oneline -family inet addr show eth1 | awk '{print $4}' 192.168.1.111/24 \[vagrant@vagrant-centos64 sbin\]$ ip -oneline -family inet addr show eth1 | awk '{print $4}' | cut -d'/' -f1 192.168.1.111 \[vagrant@vagrant-centos64 sbin\]$ 当我们在接口数组中获取设备名称并在地址数组中获取 IP 地址时,我们创建一个关联数组,其中接口名称作为键,IP 地址作为值。 return array\_combine($interfaces, $addreses); ### 使用 ifconfig 的服务器 在 ifconfig 的情况下,`ip` 的 `shell_exec` 将返回 `false`。在这种情况下,我们改为运行 ifconfig。 我们上面介绍的逻辑完全相同 - 它只是获取信息的不同实用程序。 if (!$output) { // It didn't work with "ip" , so we do it with ifconfig $output = \`ifconfig | grep "Link encap" | awk '{ print $1 }'\`; $interfaces = explode("\\n", $output); $output = \`ifconfig | grep "inet addr" | awk '{ print $2 }' | sed 's/addr://'\`; $addreses = explode("\\n", $output); $output = trim($output, " \\n"); return array\_combine($interfaces, $addreses); } 让我们在终端中运行上面的命令,以便我们了解发生了什么。 请注意,`ifconfig` 直接在输出中显示 IP 地址,因此我们可以直接获取它们,而不是在设备数组上运行循环并获取每个设备的 IP 地址。 \[vagrant@vagrant-centos64 sbin\]$ ifconfig eth0 Link encap:Ethernet HWaddr 08:00:27:08:C2:E4 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe08:c2e4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4230 errors:0 dropped:0 overruns:0 frame:0 TX packets:2575 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:444488 (434.0 KiB) TX bytes:2288676 (2.1 MiB) eth1 Link encap:Ethernet HWaddr 08:00:27:EB:11:E4 inet addr:192.168.1.111 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:feeb:11e4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4470 errors:0 dropped:0 overruns:0 frame:0 TX packets:2449 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1689803 (1.6 MiB) TX bytes:271675 (265.3 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:264 errors:0 dropped:0 overruns:0 frame:0 TX packets:264 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:15840 (15.4 KiB) TX bytes:15840 (15.4 KiB) \[vagrant@vagrant-centos64 sbin\]$ ifconfig | grep "Link encap" eth0 Link encap:Ethernet HWaddr 08:00:27:08:C2:E4 eth1 Link encap:Ethernet HWaddr 08:00:27:EB:11:E4 lo Link encap:Local Loopback \[vagrant@vagrant-centos64 sbin\]$ ifconfig | grep "Link encap" | awk '{ print $1 }' eth0 eth1 lo \[vagrant@vagrant-centos64 sbin\]$ ifconfig | grep "inet addr" inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet addr:192.168.1.111 Bcast:192.168.1.255 Mask:255.255.255.0 inet addr:127.0.0.1 Mask:255.0.0.0 \[vagrant@vagrant-centos64 sbin\]$ ifconfig | grep "inet addr" | awk '{ print $2 }' addr:10.0.2.15 addr:192.168.1.111 addr:127.0.0.1 \[vagrant@vagrant-centos64 sbin\]$ ifconfig | grep "inet addr" | awk '{ print $2 }' | sed 's/addr://' 10.0.2.15 192.168.1.111 127.0.0.1 \[vagrant@vagrant-centos64 sbin\]$ 一旦我们有了数据,将它们放入 `get_content` 中就很容易了,因为我们在这里只显示了一个简单的表格。 public function get\_content() { $interfaces = $this->get\_metric(); $html = ''; foreach ( $interfaces as $interface => $ip ) { $html .= ""; } $html .= '
Interface IP
{$interface} {$ip}
'; echo $html; } 以下是它向管理员显示的方式: ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054998.jpg) ## 网络流量 网络流量或网络 IO 显示通过计算机网络传输包的状态。该信息是从 netstat 中提取的。 \[vagrant@vagrant-centos64 sbin\]$ netstat -i Kernel Interface table Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg eth0 1500 0 4828 0 0 0 2933 0 0 0 BMRU eth1 1500 0 4806 0 0 0 2679 0 0 0 BMRU lo 16436 0 276 0 0 0 276 0 0 0 LRU 让我们在文件 `widget/networkio.php` 中获取我们的基本类 `Networkio` get\_metric(); $data = array\_merge(array(array('Interface', 'Receive(package)', 'Transfer(package)')), $interfaces); $data = json\_encode($data); echo << EOD; } 我们之前使用了条形图,并尝试将指标数据数组格式化为条形图数据格式,然后进行渲染。 数据数组的每一行代表一个组条形图,其中包含条形图名称及其相应的值。在我们的例子中,每一行都是接口名称以及 RX 栏和 TX 栏。 这是我们得到的: ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054585.jpg) ### 输入/输出统计 现在,我们处理 `io stat`。 IO 表示输入/输出。我们将了解每秒执行多少次读/写操作。我们还处理 `io_wait`。 IO等待是CPU空闲等待从硬盘读取结果的时间。 比如你正在读取MySQL数据,CPU会空闲下来等待结果。 `io wait` 按1秒或1000毫秒计算。如果您的代码需要 100 毫秒从硬盘读取数据,则 `io_wait` 为 100/1000 = 10%。 IO 等待越少,系统性能越好。 为了继续执行此操作,请确保系统上有 **sysstat** 软件包。 1. 对于 Arch Linux,使用 pacman -S sysstat 安装 2. 对于 Debian/Ubuntu,您可以使用 `apt-get install sysstat` 获取它们 3. 对于 Fedora/Centos,您可以使用 `yum install sysstat` 4. 对于其他发行版,:请使用您的发行版包管理器进行安装 安装完成后,让我们评估一下我们将使用的一些命令。首先是第一件事: \[vagrant@vagrant-centos64 sbin\]$ iostat Linux 2.6.32-358.23.2.el6.x86\_64 (vagrant-centos64.vagrantup.com) 04/27/2014 \_x86\_64\_ (1 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.05 0.00 0.25 0.04 0.00 99.66 Device: tps Blk\_read/s Blk\_wrtn/s Blk\_read Blk\_wrtn sda 0.18 7.62 1.04 157826 21584 第四行包含IO状态数据。我们对第四列中的 `iowait` 值感兴趣。从第七行开始的数据包含硬盘驱动器每秒的读/写块。 如果您有许多硬盘连接到服务器,您将拥有多个设备:sdb、sdc 等。 数据是块的数量,而不是实际大小(以兆字节为单位)。我们必须找到块大小来计算总大小。 块大小存储在/sys/block/sda/queue/physical\_block\_size**中。** \[vagrant@vagrant-centos64 ~\]$ cat /sys/block/sda/queue/physical\_block\_size 512 \[vagrant@vagrant-centos64 ~\]$ 所以我的sda的块大小是512。我们将每秒读取的块数与块大小相乘,得到读/写数据的实际大小。 有了上面的基本知识,让我们在 `widget/iostat.php` 中创建我们的类 `Iostat` 。 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; } } 我们只是尝试将我们的理论应用到 PHP 代码中。获取 `iostat` 的输出,将其转换为数组,每一行都是一个元素。 第四行被空格分割并映射到关联数组中。第七行之后的所有行都放入另一个关联数组中,其中键是设备名称(sda,sdb,sdc,..),如果以兆字节为单位读取和写入,则值是一个数组。 一旦我们获得了指标,将其输入 `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; } 对于磁盘 IO 读写,我们使用了条形图。对于 IO 等待,我们使用仪表图来使其看起来更漂亮。我们认为 80-100 的 IOwait 是一个严重事件,并用红色突出显示。 ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054705.jpg) 以上就是将Transforming a WordPress Server Dashboard into a Widget的详细内容,更多请关注知企PROSAAS其它相关文章! ![](images/2023/1212/logo.png) 智能AI问答 PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。 我要提问 相关标签: php JavaScript ruby mysql 架构 json html print 关联数组 sort foreach 命名空间 format cURL 字符串 循环 接口 堆 线程 对象 事件 linux ubuntu centos debian WordPress 来源:知企PROSAAS ![](images/2023/1212/shoucang_2x.png) 收藏 ![](images/2023/1212/icon37.png) 点赞 上一篇:WooCommerce 初学者:掌握订单创建第 3 部分 下一篇:Envato WordPress 工具包:精明的 WordPress 开发人员必备的工具箱 ![](images/2023/1212/benzhanshengming.png) 本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn 作者最新文章 - Microsoft 首席营销官揭示 Copilot 在 2024 年的未来规划 2023-12-06 08:43:56 - 微软测试 Bing 深度搜索:借助 GPT-4 进行强化,速度较普通搜索更慢 2023-12-06 08:43:49 - 阅文集团将改编超百部 IP 短剧,首部双人互动影视即将上线 2023-12-05 21:55:07 - 消息称 TikTok 将与印尼科技公司 GoTo 共同发展电商业务 2023-12-05 18:57:23 - 新标题:我国成功研发全球首艘、世界最大核动力集装箱船,采用第四代堆型熔盐反应堆解决方案 2023-12-05 18:51:02 - 华为与奇瑞合作新动向:智界第二款车型EHY预计明年下半年上市 2023-12-05 17:58:01 - 侧边指纹解锁与超声波技术的激烈竞争:小米MIX Fold 3与vivo引领前沿技术对决 2023-12-05 17:34:46 - 不仅仅依赖庞大模型,构建生成式人工智能的要求更多 2023-12-05 17:21:17 - 没有数据智能的人工智能是人工的 2023-12-05 17:15:16 - 腾讯 NOW 直播将于 12 月 26 日停止运营,已服务用户超过 7 年 2023-12-05 15:31:20 最新问题 Laravel Cashier - Stripe 多种付款方式 我的餐厅使用LaravelCashier和Stripe。我想为我的客户使用Stripe支持的多种付款方式,但我在LaravelCashier文档中找不到有关在Stripe中使用多种... P粉652495194来自于2023-12-11 18:56:12 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)2 ![](images/2023/1212/icon43.png)213 FastAPI: 如何在HTML文件中同时渲染CSS/JS/Images? 我在FastAPI中渲染HTMl文件时遇到问题。ma​​in.py文件static\_dir=os.path.join(os.path.dirname(\_\_file\_\_),"... P粉237125700来自于2023-12-11 17:58:49 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)1 ![](images/2023/1212/icon43.png)239 老师,笔记能分享一下吗 老师,笔记能分享一下吗 手机用户3055476来自于2023-12-12 16:46:38 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)0 ![](images/2023/1212/icon43.png)24 Nuxt 构建错误:TypeError:无法解构属性“nuxt”的“这个”因为它是未定义的 我想创建一个新的Nuxt项目并按照此处的说明进行操作:https://nuxtjs.org/docs/get-started/installation。基本上只是运行npminit... P粉156415696来自于2023-12-11 16:47:40 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)2 ![](images/2023/1212/icon43.png)168 CSS径向渐变到SVG径向渐变 是否可以在SVG中制作径向渐变,就像在CSS中一样http://codepen.io/A973C/pen/hnEaf(我指的是交通灯中的灯).red{background:red;... P粉308783585来自于2023-12-11 15:54:09 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)2 ![](images/2023/1212/icon43.png)242 未定义类型“Validator”.intelephense(1009) 谁能帮我解决这个错误吗?我是Laravel新手,我正在制作一个ProductController文件,但我从Validator收到此错误:我已经调用了useValidator;我还... P粉010967136来自于2023-12-11 15:05:11 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)1 ![](images/2023/1212/icon43.png)196 Laravel 9 上未找到混合清单 - vite 当我运行npmrunbuild时遇到问题,它说找不到混合清单。当我在生产中运行时会发生这种情况。我的npm-v是9.1.2并运行laravel9,带有“php”:“^8.0.2”。... P粉974462439来自于2023-12-11 13:40:48 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)1 ![](images/2023/1212/icon43.png)217 Vue3:如何将参数发送到路由而不将它们添加到 Vue3 中的 url 中? 在Vue3中,有没有一种方法可以将属性传递给路由,而无需在url中显示值?我这样定义路线:{path:'/someRoute',name:'someRoute',component... P粉465675962来自于2023-12-11 13:07:20 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)1 ![](images/2023/1212/icon43.png)214 在JSP bean中实现动态文本框及其值的提交 我有一个带有几个预定义文本框的表单,现在除此之外我还创建了一些动态文本框,我可以用javascript来完成它(我猜)。提交表单时,如何将动态生成的文本框的值设置为bean。在be... P粉916760429来自于2023-12-11 11:56:28 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)1 ![](images/2023/1212/icon43.png)190 识别特定行具有一致值的列名 我正在尝试在mysql中进行查询以获取某一特定行具有特定值的任何列。在Mysql中,我们可以根据列的任何特定值获取行。我有一个像这样的表:+----+------------+--... P粉738046172来自于2023-12-11 09:56:34 ![](images/2023/1212/icon37.png)0 ![](images/2023/1212/icon24.png)1 ![](images/2023/1212/icon43.png)133 相关专题 更多> - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054449.png) php文件怎么打开 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054772.png) php怎么取出数组的前几个元素 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054819.png) php反序列化失败怎么办 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054553.png) php怎么连接mssql数据库 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054172.png) php连接mssql数据库的方法 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054844.png) html怎么上传 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054365.png) PHP出现乱码怎么解决 - ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054894.png) php怎么在浏览器运行 热门推荐 - wordpress收费么 - WordPress 中functions.php 文件的 5 个实际应用 - 在 WordPress 中使用 Dashicons:综合指南 - 重置 WordPress 网站的指南 - 使用免费插件在WordPress中创建联系表单 - 从 WordPress 网站提取帖子的指南 - 重温 Squire:高效的 HTML5 富文本编辑器 - 创建 WordPress 登陆页面:分步指南 - 在 WordPress 中进行 A/B 测试的指南 - 修改WordPress中的特色图像大小 热门教程 更多> 相关推荐 热门推荐 最新课程 - ![](images/2023/1212/62611ef88fcec821.jpg) phpStudy极速入门视频教程 511152次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/5d1c6ddbecdb1707.jpg) 独孤九贱(1)\_HTML5视频教程 590293次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/5d1c6e053065c808.jpg) 独孤九贱(5)\_ThinkPHP5视频教程 1175339次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/620debc3eab3f377.jpg) 最新ThinkPHP 5.1全球首发视频教程(60天成就PHP大牛线上培训班课) 1354338次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/5d1c6dfc9eb09885.jpg) 独孤九贱(4)\_PHP视频教程 1175042次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/5d2426f409839992.jpg) PHP实战天龙八部之仿爱奇艺电影网站 729195次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/6253ddf274262146.png) PHP入门视频教程之一周学会PHP 1419956次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/6253d87459486427.png) ThinkPHP5实战之\[教学管理系统\] 690708次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/656e9d6795199395.png) laravel和swoole连接池操作数据库的细节分析 317次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/6568318c8aac3280.png) 微信小程序开发--组件篇--十天技能课堂 2102次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/6565567e0c514103.png) ThinkPHP6.x 微实战--十天技能课堂 1509次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/656431da5ea28258.png) Vue.js 微实战--十天技能课堂 942次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 - ![](images/2023/1212/65603b73b5002648.png) ThinkPHP6.x API接口--十天技能课堂 992次学习 ![](images/2023/1212/icon-small-nocollect.png)收藏 $('.wzrthreeTab>div').click(function(e){ $('.wzrthreeTab>div').removeClass('check') $(this).addClass('check') $('.wzrthreelist>ul').css('display','none') $('.'+e.currentTarget.dataset.id).show() }) (window.slotbydup = window.slotbydup || \[\]).push({ id: "u6938610", container: "\_u9zo4aprzs", async: true }); 最新下载 更多> - ![](images/2023/1212/170176891671079.jpg) - ![](images/2023/1212/170176891588397.jpg) - ![](images/2023/1212/170176891442795.jpg) $(document).ready(function(){ var sjyx\_banSwiper = new Swiper(".sjyx\_banSwiperwz",{ speed:1000, autoplay:{ delay:3500, disableOnInteraction: false, }, pagination:{ el:'.sjyx\_banSwiperwz .swiper-pagination', clickable :false, }, loop:true }) }) 网站特效 网站源码 网站素材 前端模板 - \[焦点幻灯\] js左侧分类菜单图片轮播代码 - \[焦点幻灯\] jQuery百叶窗风格图片切换代码 - \[焦点幻灯\] jQuery仿京东首页广告图片切换 - \[焦点幻灯\] jQuery无缝轮播插件 - \[焦点幻灯\] jQuery自适应三屏滚动代码 - \[焦点幻灯\] jQuery仿今日头条图片轮播代码 - \[焦点幻灯\] jQuery爆炸切换效果焦点图 - \[焦点幻灯\] jQuery仿魅族大图轮播幻灯片特效 - \[Bootstrap模板\] 有机果蔬供应商网页模板 Bootstrap5 - \[后端模板\] Bootstrap3多功能数据信息后台管理响应式网页模板-Novus - \[Bootstrap模板\] 房产资源服务平台网页模板 Bootstrap5 - \[Bootstrap模板\] 简约简历资料网页模板 Bootstrap4 - \[Bootstrap模板\] bootstrap响应式宽屏图书教育网站模板-DREAMLIFE - \[后端模板\] MAC风格响应式蓝色企业CMS后台管理系统模版 - \[后端模板\] 响应式渐变大气后台管理系统网站模板-usinessbox - \[Bootstrap模板\] 响应式蔬菜水果商店网站模板-Organio - \[网站素材\] 九个不同动作和表情的柠檬矢量素材(EPS) - \[网站素材\] 蓝色的世界地图矢量素材(EPS+PNG) - \[网站素材\] 九个手绘黑白风格的山脉矢量素材(EPS+PNG) - \[网站素材\] 八个不同种族和肤色的人物头像矢量素材(AI+EPS+PNG) - \[网站素材\] 15个水墨笔刷集合矢量素材(EPS+PNG) - \[网站素材\] 逼真的银色 MacBook Pro 电脑模型矢量素材(EPS+PNG) - \[网站素材\] 可爱的 happy birthday to you 字母矢量素材(AI+EPS+PNG) - \[网站素材\] 带着 VR 眼睛访问网络体验科技的人们矢量素材(EPS) - \[前端模板\] HTML5进出口水果公司宣传网站模板 - \[前端模板\] 用户界面设计服务公司网站模板 - \[前端模板\] 响应式清洁消毒家政服务网站模板 - \[前端模板\] 我们要结婚了婚礼邀请函网页模板 - \[前端模板\] HTML5新闻资讯分享网站模板 - \[前端模板\] 时尚冬装在线购物商城网站模板 - \[前端模板\] 响应式在线学习资源网站模板 - \[前端模板\] 物流运输服务公司宣传网站模板 $('.wzrfourlTab>div').click(function(e){ $('.wzrfourlTab>div').removeClass('check') $(this).addClass('check') $('.wzrfourList>ul').css('display','none') $('.'+e.currentTarget.dataset.id).show() }) 关于我们 免责申明 意见反馈 讲师合作 广告合作 技术文章 知企PROSAAS:公益在线php培训,帮助PHP学习者快速成长! 关注服务号 _ 微信扫码 关注PHP中文网服务号 ![](images/2023/1212/text16.png) _ 技术交流群 _ QQ扫码 加入技术交流群 ![](images/2023/1212/text18.png) _ app下载 ![](images/2023/1212/text14.png) 扫描下载App ![](images/2023/1212/text17.png) PHP中文网订阅号 每天精选资源文章推送 ![](images/2023/1212/text14.png) PHP中文网APP 随时随地碎片化学习 ![](images/2023/1212/dy.png) PHP中文网抖音号 发现有趣的 Copyright 2014-2023 https://www.php.cn/ All Rights Reserved | 苏州跃动光标网络科技有限公司 | 湘ICP备2023035733号 var \_hmt = \_hmt || \[\]; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?c0e685c8743351838d2a7db1c49abd56"; var s = document.getElementsByTagName("script")\[0\]; s.parentNode.insertBefore(hm, s); })(); layui.use(\['element', 'carousel'\], function () {var element = layui.element;$ = layui.jquery;var carousel = layui.carousel;carousel.render({elem: '#test1', width: '100%', height: '330px', arrow: 'always'});$.getScript('/static/js/jquery.lazyload.min.js', function () {$("img").lazyload({placeholder: "/static/images/load.jpg", effect: "fadeIn", threshold: 200, skip\_invisible: false});});}); $(function() { //直播倒计时 $(".liveitem").each(function(){ timer(this); }) function timer(obj){ var intDiff = $(obj).data("countdown"); window.setInterval(function(){ var day=0, hour=0, minute=0, second=0;//时间默认值 if(intDiff > 0){ day = Math.floor(intDiff / (60 \* 60 \* 24)); hour = Math.floor(intDiff / (60 \* 60)) - (day \* 24); minute = Math.floor(intDiff / 60) - (day \* 24 \* 60) - (hour \* 60); second = Math.floor(intDiff) - (day \* 24 \* 60 \* 60) - (hour \* 60 \* 60) - (minute \* 60); }else{ $(obj).find(".phpZbktBg").remove(); return; } if (hour <= 9) hour = '0' + hour; if (minute <= 9) minute = '0' + minute; if (second <= 9) second = '0' + second; $(obj).find('.day\_show').html(day+""); $(obj).find('.hour\_show').html(''+hour+''); $(obj).find('.minute\_show').html(''+minute+''); $(obj).find('.second\_show').html(''+second+''); intDiff--; }, 1000); } }); article\_status = 164; var \_hmt = \_hmt || \[\];(function(){var hm = document.createElement("script");hm.src="//hm.baidu.com/hm.js?c0e685c8743351838d2a7db1c49abd56";var s=document.getElementsByTagName("script")\[0\];s.parentNode.insertBefore(hm, s);})();(function(){var bp = document.createElement('script');var curProtocol = window.location.protocol.split(':')\[0\];if(curProtocol === 'https'){bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';}else{bp.src = 'http://push.zhanzhang.baidu.com/push.js';};var s = document.getElementsByTagName("script")\[0\];s.parentNode.insertBefore(bp, s);})(); var topadshow = $.cookie('phpcndatatopadshows');if(!topadshow&&1==2){$('.topimages').show();var topobj = $('.topimages').find('.time');var topobj\_day = $('.topimages .time').find('.day');var topobj\_hours = $('.topimages .time').find('.hours');var topobj\_minutes = $('.topimages .time').find('.minutes');var topobj\_second = $('.topimages .time').find('.second');var topday = parseInt(topobj\_day.html());var tophours = parseInt(topobj\_hours.html());var topminutes = parseInt(topobj\_minutes.html());var topsecond = parseInt(topobj\_second.html());setInterval(function(){if(topsecond > 0){topsecond = topsecond-1;}else{if(topminutes > 0){topminutes = topminutes-1;topsecond = 59;}else{if(tophours > 0){tophours = tophours-1;topminutes = 59;topsecond = 59;}else{if(topday > 0){topday = topday -1;tophours = 23;topminutes = 59;topsecond = 59;}else{topobj.html(" 活动已结束 ");}}}}topobj\_second.html(topsecond);topobj\_minutes.html(topminutes);topobj\_hours.html(tophours);topobj\_day.html(topday);},1000);}$('.topimages .layui-icon-close').click(function(){$.cookie('phpcndatatopadshows',1,{expires:7});$('.topimages').hide();}); .content img{max-width:80%;} .copy-button { padding: 5px 10px; background-color: #666; border: none; color: #FFF; font-size: 12px; cursor: pointer; border-radius: 5px; position: relative; top: 33px; right: 5px; z-index: 99; float: right; } .copy-button:hover { background-color: #fc3930; } $(document).ready(function(){ $('#gongzhonghao').hover(function(){ $('#gzh').show(); },function(){ $('#gzh').hide(); }) }) layui.use(\['jquery','layer'\], function(){ $('.test-iframe-handle').click(function(){ layer.open({ type: 2, area: \['1300px', '750px'\], content: 'https://www.php.cn/help/ask?q=%E5%B0%86Transforming+a+WordPress+Server+Dashboard+into+a+Widget', fixed: true, // 不固定 //maxmin: true, shadeClose: true, title:"智能小助手", btnAlign: 'c', yes: function(index, layero){ // 获取 iframe 的窗口对象 var iframeWin = window\[layero.find('iframe')\[0\]\['name'\]\]; var elemMark = iframeWin.$('#mark'); // 获得 iframe 中某个输入框元素 var value = elemMark.val(); if($.trim(value) === '') return elemMark.focus(); // 显示获得的值 layer.msg('获得 iframe 中的输入框标记值:'+ value); } }); }) var is\_login = "0"; var show = 0; var ceng = getCookie('ceng'); //文章下拉弹出登录 if(is\_login == 0 && !ceng) { window.onscroll = function(){ var t = document.documentElement.scrollTop || document.body.scrollTop; var top\_div = document.getElementById( "top\_div" ); if( t >= 2500 && show == 0) { show = 1 setCookie('ceng',1,1); $(document).trigger("api.loginpopbox"); } } } //未登录复制显示登录按钮 if(is\_login == 0) { $(".code").hover(function(){ $(this).find('.contentsignin').show(); },function(){ $(this).find('.contentsignin').hide(); }); //不给复制 $('.code').bind("cut copy paste",function(e) { e.preventDefault(); }); $('.code .contentsignin').click(function(){ $(document).trigger("api.loginpopbox"); }) }else { // 获取所有的 元素 var preElements = document.querySelectorAll('pre'); // 遍历每个 元素 preElements.forEach(function(preElement) { // 创建复制按钮 var copyButton = document.createElement('button'); copyButton.className = 'copy-button'; copyButton.textContent = '复制'; // 添加点击事件处理程序 copyButton.addEventListener('click', function() { // 获取当前按钮所属的 元素中的文本内容 var textContent = preElement.textContent.trim(); // 创建一个临时 textarea 元素并设置其值为 中的文本内容 var tempTextarea = document.createElement('textarea'); tempTextarea.value = textContent; // 将临时 textarea 添加到文档中 document.body.appendChild(tempTextarea); // 选中临时 textarea 中的文本内容并执行复制操作 tempTextarea.select(); document.execCommand('copy'); // 移除临时 textarea 元素 document.body.removeChild(tempTextarea); // 更新按钮文本为 "已复制" this.textContent = '已复制'; }); // 将按钮添加到 元素前面 preElement.parentNode.insertBefore(copyButton, preElement); }); } }) function setCookie(name,value,iDay){ //name相当于键,value相当于值,iDay为要设置的过期时间(天) var oDate = new Date(); oDate.setDate(oDate.getDate() + iDay); document.cookie = name + '=' + value + ';path=/;domain=.php.cn;expires=' + oDate; } function getCookie(name) { var cookieArr = document.cookie.split(";"); for(var i = 0; i < cookieArr.length; i++) { var cookiePair = cookieArr\[i\].split("="); if(name == cookiePair\[0\].trim()) { return decodeURIComponent(cookiePair\[1\]); } } return null; } window.onload = function() { // 在这里引用需要延迟加载的 JavaScript 文件 var script = document.createElement('script'); script.src = 'https://cdn.wwads.cn/js/makemoney.js'; document.body.appendChild(script); }; function aiask(ask){ layer.open({ type: 2, area: \['1300px', '750px'\], content: 'https://www.php.cn/help/ask?q='+encodeURIComponent(ask), fixed: true, // 不固定 //maxmin: true, shadeClose: true, title:"智能小助手", btnAlign: 'c', yes: function(index, layero){ // 获取 iframe 的窗口对象 var iframeWin = window\[layero.find('iframe')\[0\]\['name'\]\]; var elemMark = iframeWin.$('#mark'); // 获得 iframe 中某个输入框元素 var value = elemMark.val(); if($.trim(value) === '') return elemMark.focus(); // 显示获得的值 layer.msg('获得 iframe 中的输入框标记值:'+ value); } }); } 登录PHP中文网,和优秀的人一起学习! 全站2000+教程免费学 微信扫码登录 .layui-fixbar{display: none;} - 精品班 - 技术支持 - 技术咨询 ![](//zhiqipro.oss-cn-beijing.aliyuncs.com/2023/12/20231212123054883.png) - 学习群 - 会员优惠 - 返回顶部 **Tags:** centos, cURL, debian, foreach, format, html, JavaScript, json, linux, mysql **Categories:** WordPress ---