当前位置:首页 > PHP教程 > php应用 > 列表

PHP 获取 Linux 系统 CPU 负载的例子

发布:smiling 来源: PHP粉丝网  添加日期:2018-09-17 09:52:10 浏览: 评论:0 

最近使用 PHP 做了一个服务器负载监控的小东西,在服务器上使用 Workerman 开一个 WebSocket 服务,然后在浏览器中连接到服务。服务每隔 10 秒读取一次主机的相关信息,然后发送给客户端,客户端进行图形化显示。

总体的思路就是使用 PHP 调用 shell 命令,然后解析命令的输出内容。在获取 CPU 负载的时候,遇到了一些小问题。直观来说,直接使用 vmstat 命令就可以获取 CPU 负载,但是实际上,vmstat 命令第一行输出的从主机启动以来的平均 CPU 负载,并不是当前的负载。vmstat 命令还有一些参数,比如可以增加一个延迟参数 delay: vmstat 1,表示每秒输出一次数据,直到用户终止命令:

  1. miroot@miserver:~$ vmstat 1 
  2. procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 
  3.  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 
  4.  4  0      0 493644 162940 5727744    0    0     2    15    0    0  1  0 99  0 
  5.  0  4      0 568392 162952 5656868    0    0   112 15584 8807 4496 29  6 57  7 
  6.  3  0      0 567152 162952 5657416    0    0    40   116 10104 5164 28  6 65  2 
  7.  2  1      0 566368 162956 5658476    0    0    84 22220 11126 5632 29  7 58  5 
  8.  2  2      0 563320 162964 5659200    0    0    56 49240 9765 4792 21  7 53 19 
  9.  0  0      0 566464 162976 5659892    0    0    80  1212 9998 5135 26  6 59  9 
  10.  2  0      0 565400 162984 5660736    0    0    92   120 9288 4954 29  5 66  1 
  11.  ^C 
  12. miroot@miserver:~$ 

第一行数据是平均负载,从第二行数据开始,是当前的负载情况。作为监控来讲,肯定更加关注当前的负载情况。

那么,使用 PHP 调用 vmstat,当然不能使用延迟的方式来等待后续行的输出。

查了一些文档,发现在 Linux 上,系统负载的情况在 /proc/stat 这个文件中,这个文件中的内容比较多,所以我们换一个思路,采用 vmstat -s 的方式直接输出内容:

  1. miroot@miserver:~$ vmstat -s 
  2.       8165768 K total memory 
  3.       4600664 K used memory 
  4.       1980464 K active memory 
  5.       2249908 K inactive memory 
  6.       3565104 K free memory 
  7.        232532 K buffer memory 
  8.       2972048 K swap cache 
  9.       8378364 K total swap 
  10.        253352 K used swap 
  11.       8125012 K free swap 
  12.       1170373 non-nice user cpu ticks 
  13.         25184 nice user cpu ticks 
  14.        294692 system cpu ticks 
  15.    1309152182 idle cpu ticks 
  16.       1867039 IO-wait cpu ticks 
  17.           566 IRQ cpu ticks 
  18.         76405 softirq cpu ticks 
  19.             0 stolen cpu ticks 
  20.       4601555 pages paged in 
  21.      96400000 pages paged out 
  22.          1516 pages swapped in 
  23.         67468 pages swapped out 
  24.     243751059 interrupts 
  25.     384963258 CPU context switches 
  26.    1455419401 boot time 
  27.        184668 forks 
  28. miroot@miserver:~$ 

可以看到,这里面包含很多和 CPU 相关的数据,实际上这个数据的来源就是 /proc/stat 文件。那么我们关心这么几项数据:

  1. 1170373 non-nice user cpu ticks 
  2.   25184 nice user cpu ticks 
  3.  294692 system cpu ticks 
  4. 9152182 idle cpu ticks 

通过 man 5 proc 找到关于 /proc/stat 文件的说明,我们关心的是 CPU 相关数据的说明:

  1. The  amount  of  time,  measured  in  units  of  USER_HZ  (1/100ths  of  a  second  on  most   architectures, use sysconf(_SC_CLK_TCK) to obtain the right value), that the system spent in various states: 
  2. user   (1) Time spent in user mode. 
  3. nice   (2) Time spent in user mode with low priority (nice). 
  4. system (3) Time spent in system mode. 
  5. idle   (4)  Time  spent  in the idle task.  This value should be USER_HZ times the second entry in the /proc/uptime pseudo-file. 

大概的意思就是说,这些数值都是以 USER_HZ 为单位的。不管什么单位,总之他们的单位是一致的,那么我们就可以通过 2 次 vmstat -s 命令的输出来计算每个项上的增量,然后 4 个项上的增量相加就是总体的增量(其实后面还有更多关于 CPU 的数据,我们先忽略掉),然后计算每个项上的增量和总体增量的比,就是在这两次采样之间 CPU 在用户、系统和闲置状态下的负载。

参考代码如下:

  1. // 在 Linux 系统上,需要使用 2 次 vmstat -s 
  2. // 结果的差值来计算两次采样之间的 CPU 占用比例 
  3. $last_cpu_ticks = array
  4.     0, // non-nice user cpu ticks 
  5.     0, // nice user cpu ticks 
  6.     0, // system cpu ticks 
  7.     0  // idle cpu ticks 
  8.     ); 
  9. function _get_cpu_status_linux() 
  10.     global $last_cpu_ticks
  11.  
  12.     $s = shell_exec('vmstat -s | grep cpu'); 
  13.     if ($s === false) return false; 
  14.     $lines = explode("n"$s); 
  15.     if (count($lines) < 4) return false; 
  16.     $current_data = array(); 
  17.     for ($i = 0; $i < 4; $i++)  
  18.     { 
  19.         $current_data[] = (int)(explode(' ', trim($lines[$i]))[0]); 
  20.     } 
  21.      
  22.     $ret = array('user' => 0, 'sys' => 0, 'idle' => 0); 
  23.  
  24.     if ($last_cpu_ticks[0] > 0)  
  25.     {    
  26.         $total_delta = 0; 
  27.         foreach ($current_data as $i => $v)  
  28.             $total_delta += ($v - $last_cpu_ticks[$i]); 
  29.  
  30.         $ret['user'] = (int)(($current_data[0] - $last_cpu_ticks[0] + $current_data[1] - $last_cpu_ticks[1]) / $total_delta * 100); 
  31.         $ret['sys'] = (int)(($current_data[2] - $last_cpu_ticks[2]) / $total_delta * 100); 
  32.         $ret['idle'] = (int)(($current_data[3] - $last_cpu_ticks[3]) / $total_delta * 100); 
  33.     } //phpfensi.com 
  34.  
  35.     for ($i = 0; $i < 4; $i++)  
  36.         $last_cpu_ticks[$i] = $current_data[$i]; 
  37.  
  38.     return $ret
  39. }

Tags: 例子 系统

分享到: