35

Is there a way to know the avaliable ram in a server (linux distro) with php (widthout using linux commands)?

edit: sorry, the objective is to be aware of the ram available in the server / virtual machine, for the particular server (even if that memory is shared).

yoda
  • 9,912
  • 19
  • 61
  • 90

9 Answers9

41

If you know this code will only be running under Linux, you can use the special /proc/meminfo file to get information about the system's virtual memory subsystem. The file has a form like this:

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

That first line, MemTotal: ..., contains the amount of physical RAM in the machine, minus the space reserved by the kernel for its own use. It's the best way I know of to get a simple report of the usable memory on a Linux system. You should be able to extract it via something like the following code:

<?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"; ?>

(Please note: this code may require some tweaking for your environment.)

ddjikic
  • 1,131
  • 10
  • 26
rcoder
  • 10,701
  • 1
  • 20
  • 19
  • 6
    upvoted for the meminfo, with 3 gotchas: - its NOT '/proc/meminfo.txt', but '/proc/meminfo' - you should match 'MemFree', and not 'MemTotal'. - and you forgot fclose() ;) – J.C. Inacio Sep 21 '09 at 17:08
  • You're right that the `.txt` suffix is wrong, but I did mean to use `MemTotal`, not `MemFree` -- perhaps I misunderstood the original question, though. Re-reading it, I see the word "available", though I'm honestly not sure how knowing the *available* RAM on a server helps all that much, given the nature of modern VM and cache subsystems. Also, the omission of `fclose()` shouldn't really be a factor for short-lived PHP scripts, correct? It's hard to leak file descriptors when your GC can finalize open handles... – rcoder Sep 21 '09 at 17:50
  • I don't think parsing system files with a script is a good idea when we can run simple shell commands to get the same result. – fotuzlab Nov 25 '13 at 09:59
  • Subtract the value from "Buffers:" and "Cached:" lines in order to avoid counting disk cache as used memory, eg if you want to see how much memory is left for applications to use. – Bell Nov 25 '15 at 15:13
  • That is, MemTotal - MemFree - Buffers - Cached = [memory used by applications] – Bell Nov 25 '15 at 15:37
37

Using /proc/meminfo and getting everything into an array is simple:

<?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"
  ...
Hassaan
  • 6,355
  • 5
  • 25
  • 44
J.C. Inacio
  • 4,274
  • 2
  • 19
  • 24
  • 5
    You might want to add a trim() on the result of file_get_contents. I was getting a trailing line ending, resulting in a empty array key, which in turn generates a PHP warning – Sebastiaan Hilbers Sep 16 '14 at 07:05
  • 2
    I guess this is the best option, because the question has not ask about free ram, just ram values, that can be, free, total, etc. – m3nda Dec 15 '14 at 04:34
  • Hi .. above values which are being fetch are in kb .. what should be done to fetch it in GB. – pihu May 24 '17 at 06:59
6

Linux commands can be run using the exec function in PHP. This is efficient and will do the job(if objective is to get the memory).

Try the following code:

<?php
  exec("free -mtl", $output);
  print_r($output);
?>
fotuzlab
  • 1,396
  • 1
  • 14
  • 17
3

Small and tidy function to get all of its values associated to their keys.

$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"
Mahdyfo
  • 1,077
  • 7
  • 18
1

It is worth noting that in Windows this information (and much more) can be acquired by executing and parsing the output of the shell command: systeminfo

xendi
  • 1,831
  • 3
  • 27
  • 51
1

I don't think you can access the host server memory info without a special written PHP extension. The PHP core library does not allow (perhaps for security reasons) to access the extended memory info.

However, if your script has access to the /proc/meminfo then you can query that special file and grab the info you need. On Windows (although you've not asked for it) we can use the com_dotnet PHP extension to query the Windows framework via COM.

Below you can find my getSystemMemoryInfo that returns that info for you no matter if you run the script on a Linux/Windows server. The wmiWBemLocatorQuery is just a helper function.

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];
}

Example on a 8GB RAM system

print_r(getSystemMemoryInfo());

Output

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

If you want to understand what each field represent then read more.

Eugen Mihailescu
  • 2,944
  • 1
  • 27
  • 28
1

// helpers

/**
 * @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');
}
  • 3
    Welcome to Stack Overflow! Thank you for this code snippet, which may provide some immediate help. A proper explanation [would greatly improve](//meta.stackexchange.com/q/114762) its educational value by showing *why* this is a good solution to the problem, and would make it more useful to future readers with similar, but not identical, questions. Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Jul 31 '17 at 12:17
0

shorter version

preg_match('#MemFree:[\s\t]+([\d]+)\s+kB#', file_get_contents('/proc/meminfo'), $matches); 
var_dump($matches[1]); // Free abount in KB
Elvis Ciotti
  • 4,348
  • 1
  • 21
  • 17
-2

I don't remember having ever seen such a function -- its kind of out the scope of what PHP is made for, actually.

Even if there was such a functionnality, it would probably be implemented in a way that would be specific to the underlying operating system, and wouldn't probably work on both Linux and windows (see sys_getloadavg for an example of that kind of thing)

Pascal MARTIN
  • 374,560
  • 73
  • 631
  • 650