【问题标题】:get server ram with php用 php 获取服务器内存
【发布时间】:2010-11-30 03:14:01
【问题描述】:

有没有办法通过 php(使用 linux 命令进行宽度输出)来了解服务器(linux 发行版)中可用的 ram?

编辑:抱歉,目标是了解特定服务器的服务器/虚拟机中可用的内存(即使该内存是共享的)。

【问题讨论】:

标签: php ram


【解决方案1】:

如果您知道这段代码只能在 Linux 下运行,您可以使用特殊的/proc/meminfo 文件来获取有关系统虚拟内存子系统的信息。该文件的格式如下:

MemTotal:       255908 kB
MemFree:         69936 kB
Buffers:         15812 kB
Cached:         115124 kB
SwapCached:          0 kB
Active:          92700 kB
Inactive:        63792 kB
...

第一行,MemTotal: ...,包含机器中的物理 RAM 量,减去内核保留供自己使用的空间。这是我所知道的获得 Linux 系统上可用内存的简单报告的最佳方式。您应该能够通过类似以下代码的方式提取它:

<?php
  $fh = fopen('/proc/meminfo','r');
  $mem = 0;
  while ($line = fgets($fh)) {
    $pieces = array();
    if (preg_match('/^MemTotal:\s+(\d+)\skB$/', $line, $pieces)) {
      $mem = $pieces[1];
      break;
    }
  }
  fclose($fh);

  echo "$mem kB RAM found"; ?>

(请注意:此代码可能需要针对您的环境进行一些调整。)

【讨论】:

  • 支持 meminfo,有 3 个陷阱: - 它不是 '/proc/meminfo.txt',而是 '/proc/meminfo' - 你应该匹配 'MemFree',而不是 'MemTotal'。 - 你忘了 fclose() ;)
  • 你是对的,.txt 后缀是错误的,但我的意思是使用MemTotal,而不是MemFree——也许我误解了最初的问题。重新阅读它,我看到了“可用”这个词,但老实说,鉴于现代 VM 和缓存子系统的性质,我不确定知道服务器上的 可用 RAM 有多大帮助。此外,fclose() 的遗漏不应该真的是短期 PHP 脚本的一个因素,对吗?当您的 GC 可以最终确定打开的句柄时,很难泄漏文件描述符...
  • 我不认为使用脚本解析系统文件是一个好主意,因为我们可以运行简单的 shell 命令来获得相同的结果。
  • 从“Buffers:”和“Cached:”行中减去该值,以避免将磁盘缓存计为已用内存,例如,如果您想查看还有多少内存可供应用程序使用。
  • 即MemTotal - MemFree - Buffers - Cached = [应用程序使用的内存]
【解决方案2】:

使用/proc/meminfo 并将所有内容放入数组很简单:

<?php

function getSystemMemInfo() 
{       
    $data = explode("\n", file_get_contents("/proc/meminfo"));
    $meminfo = array();
    foreach ($data as $line) {
        list($key, $val) = explode(":", $line);
        $meminfo[$key] = trim($val);
    }
    return $meminfo;
}

?>

var_dump( getSystemMemInfo() );

array(43) {
  ["MemTotal"]=>
  string(10) "2060700 kB"
  ["MemFree"]=>
  string(9) "277344 kB"
  ["Buffers"]=>
  string(8) "92200 kB"
  ["Cached"]=>
  string(9) "650544 kB"
  ["SwapCached"]=>
  string(8) "73592 kB"
  ["Active"]=>
  string(9) "995988 kB"
  ...

【讨论】:

  • 您可能希望在 file_get_contents 的结果上添加一个 trim()。我得到一个尾随行结尾,导致一个空数组键,这反过来会生成一个 PHP 警告
  • 我想这是最好的选择,因为问题没有询问免费内存,只是内存值,可以是,免费,总计等。
  • 嗨 .. 以上正在获取的值以 kb 为单位 .. 应该如何以 GB 为单位获取它。
【解决方案3】:

Linux 命令可以使用 PHP 中的exec 函数运行。这是有效的,并且可以完成工作(如果目标是获取内存)。

试试下面的代码:

<?php
  exec("free -mtl", $output);
  print_r($output);
?>

【讨论】:

    【解决方案4】:

    小而整洁的函数,用于获取与其键关联的所有值。

    $contents = file_get_contents('/proc/meminfo');
    preg_match_all('/(\w+):\s+(\d+)\s/', $contents, $matches);
    $info = array_combine($matches[1], $matches[2]);
    
    // $info['MemTotal'] = "2047442"
    

    【讨论】:

      【解决方案5】:

      我认为如果没有专门编写的 PHP 扩展,您将无法访问主机服务器内存信息。 PHP 核心库不允许(可能出于安全原因)访问扩展内存信息。

      但是,如果您的脚本可以访问/proc/meminfo,那么您可以查询该特殊文件并获取您需要的信息。在 Windows 上(尽管您没有要求它),我们可以使用 com_dotnet PHP 扩展通过 COM 查询 Windows 框架。

      您可以在下面找到我的getSystemMemoryInfo,无论您是否在 Linux/Windows 服务器上运行脚本,它都会为您返回该信息。 wmiWBemLocatorQuery 只是一个辅助函数。

      function wmiWBemLocatorQuery( $query ) {
          if ( class_exists( '\\COM' ) ) {
              try {
                  $WbemLocator = new \COM( "WbemScripting.SWbemLocator" );
                  $WbemServices = $WbemLocator->ConnectServer( '127.0.0.1', 'root\CIMV2' );
                  $WbemServices->Security_->ImpersonationLevel = 3;
                  // use wbemtest tool to query all classes for namespace root\cimv2
                  return $WbemServices->ExecQuery( $query );
              } catch ( \com_exception $e ) {
                  echo $e->getMessage();
              }
          } elseif ( ! extension_loaded( 'com_dotnet' ) )
              trigger_error( 'It seems that the COM is not enabled in your php.ini', E_USER_WARNING );
          else {
              $err = error_get_last();
              trigger_error( $err['message'], E_USER_WARNING );
          }
      
          return false;
      }
      
      // _dir_in_allowed_path this is your function to detect if a file is withing the allowed path (see the open_basedir PHP directive)
      function getSystemMemoryInfo( $output_key = '' ) {
          $keys = array( 'MemTotal', 'MemFree', 'MemAvailable', 'SwapTotal', 'SwapFree' );
          $result = array();
      
          try {
              // LINUX
              if ( ! isWin() ) {
                  $proc_dir = '/proc/';
                  $data = _dir_in_allowed_path( $proc_dir ) ? @file( $proc_dir . 'meminfo' ) : false;
                  if ( is_array( $data ) )
                      foreach ( $data as $d ) {
                          if ( 0 == strlen( trim( $d ) ) )
                              continue;
                          $d = preg_split( '/:/', $d );
                          $key = trim( $d[0] );
                          if ( ! in_array( $key, $keys ) )
                              continue;
                          $value = 1000 * floatval( trim( str_replace( ' kB', '', $d[1] ) ) );
                          $result[$key] = $value;
                      }
              } else      // WINDOWS
              {
                  $wmi_found = false;
                  if ( $wmi_query = wmiWBemLocatorQuery( 
                      "SELECT FreePhysicalMemory,FreeVirtualMemory,TotalSwapSpaceSize,TotalVirtualMemorySize,TotalVisibleMemorySize FROM Win32_OperatingSystem" ) ) {
                      foreach ( $wmi_query as $r ) {
                          $result['MemFree'] = $r->FreePhysicalMemory * 1024;
                          $result['MemAvailable'] = $r->FreeVirtualMemory * 1024;
                          $result['SwapFree'] = $r->TotalSwapSpaceSize * 1024;
                          $result['SwapTotal'] = $r->TotalVirtualMemorySize * 1024;
                          $result['MemTotal'] = $r->TotalVisibleMemorySize * 1024;
                          $wmi_found = true;
                      }
                  }
                  // TODO a backup implementation using the $_SERVER array
              }
          } catch ( Exception $e ) {
              echo $e->getMessage();
          }
          return empty( $output_key ) || ! isset( $result[$output_key] ) ? $result : $result[$output_key];
      }
      

      8GB RAM 系统上的示例

      print_r(getSystemMemoryInfo());
      

      输出

      Array
      (
          [MemTotal] => 8102684000
          [MemFree] => 2894508000
          [MemAvailable] => 4569396000
          [SwapTotal] => 4194300000
          [SwapFree] => 4194300000
      )
      

      如果你想了解每个字段代表什么,那么read more

      【讨论】:

        【解决方案6】:

        值得注意的是,在 Windows 中,这些信息(以及更多信息)可以通过执行和解析 shell 命令的输出来获取:systeminfo

        【讨论】:

        • 虽然命令非常慢,但我可以确认它可以从 PHP 成功调用。
        【解决方案7】:

        // 助手

        /**
         * @return array|null
         */
        protected function getSystemMemInfo()
        {
            $meminfo = @file_get_contents("/proc/meminfo");
            if ($meminfo) {
                $data = explode("\n", $meminfo);
                $meminfo = [];
                foreach ($data as $line) {
                    if( strpos( $line, ':' ) !== false ) {
                        list($key, $val) = explode(":", $line);
                        $val = trim($val);
                        $val = preg_replace('/ kB$/', '', $val);
                        if (is_numeric($val)) {
                            $val = intval($val);
                        }
                        $meminfo[$key] = $val;
                    }
                }
                return $meminfo;
            }
            return  null;
        }
        
        // example call to check health
        public function check() {
            $memInfo = $this->getSystemMemInfo();
            if ($memInfo) {
                $totalMemory = $memInfo['MemTotal'];
                $freeMemory = $memInfo['MemFree'];
                $swapTotalMemory = $memInfo['SwapTotal'];
                $swapFreeMemory = $memInfo['SwapFree'];
                if (($totalMemory / 100.0) * 30.0 > $freeMemory) {
                    if (($swapTotalMemory / 100.0) * 50.0 > $swapFreeMemory) {
                        return new Failure('Less than 30% free memory and less than 50% free swap space');
                    }
                    return new Warning('Less than 30% free memory');
                }
            }
            return new Success('ok');
        }
        

        【讨论】:

        • 欢迎来到 Stack Overflow!感谢您提供此代码 sn-p,它可能会提供一些即时帮助。一个正确的解释would greatly improve 其教育价值通过展示为什么这是一个很好的解决问题的方法,并将使它对未来有类似但不相同的问题的读者更有用。请edit您的答案添加解释,并说明适用的限制和假设。
        【解决方案8】:

        exec("grep MemTotal /proc/meminfo", $aryMem); $aryMem[0] 的总内存减去内核使用量。

        【讨论】:

          【解决方案9】:

          我不记得曾经见过这样的函数——实际上,它超出了 PHP 的用途。

          即使有这样的功能,它也可能会以特定于底层操作系统的方式实现,并且可能无法在 Linux 和 Windows 上运行(请参阅 sys_getloadavg这种事情的例子)

          【讨论】:

            猜你喜欢
            • 2011-07-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-03
            • 1970-01-01
            • 2018-07-04
            • 2018-01-06
            • 1970-01-01
            相关资源
            最近更新 更多