Skip to content

Instantly share code, notes, and snippets.

@abiusx
Created August 1, 2019 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abiusx/4edcf127cded0e666a49d8ae02e39b5f to your computer and use it in GitHub Desktop.
Save abiusx/4edcf127cded0e666a49d8ae02e39b5f to your computer and use it in GitHub Desktop.
System stats (network, disk, memory, sockets, cpu) in PHP for Linux
<?php
/**
* Grab a /proc/X file and parse as key value pairs separated by colon
* @param string $proc name
* @return array
*/
function parse_colon_proc($proc)
{
$res = shell_exec("cat /proc/{$proc}");
$res = explode(PHP_EOL, $res);
$out = [];
foreach ($res as $r)
{
$r = explode(":",$r);
if (count($r)<2) continue;
$out[trim($r[0])]=trim($r[1]);
}
return $out;
}
/**
* Socket statistics
* @return array
*/
function system_stat_socket()
{
$res = shell_exec("ss -s");
$res = explode(PHP_EOL, $res);
foreach ($res as &$r)
$r = array_values(array_filter(explode(" ", $r), function ($_) { return $_!=="";}));
$out = [];
$out['total'] = $res[0][1]*1;
$out['tcp']['established'] = $res[1][3]*1;
$out['tcp']['closed'] = $res[1][5]*1;
$out['tcp']['orphaned'] = $res[1][7]*1;
$out['tcp']['timewait'] = $res[1][11]*1;
$out['tcp']['total'] = $res[7][1]*1;
$out['tcp']['ip'] = $res[7][2]*1;
$out['tcp']['ipv6'] = $res[7][3]*1;
$out['udp']['total'] = $res[6][1]*1;
$out['udp']['ip'] = $res[6][2]*1;
$out['udp']['ipv6'] = $res[6][3]*1;
return $out;
}
/**
* Network statistics
*
* Uses .last file to store latest stats and time, to measure difference
* @return array
*/
function system_stat_net()
{
if (file_exists(".last"))
{
$t = json_decode(file_get_contents(".last"));
$old_devices = $t->devices;
$old_time = $t->time;
}
else
{
// time since boot
$r = shell_exec("cat /proc/uptime");
$r = explode(" ", $r)[0];
$old_time = microtime(true)-$r;
}
$res = shell_exec("cat /proc/net/dev");
$res = explode(PHP_EOL, $res);
array_shift($res); // first row
array_shift($res); // second row
$dev = $devices = [];
$time_diff = microtime(true) - $old_time;
foreach ($res as $r)
{
$t = explode(" ", $r);
$t = array_filter($t, function ($_) {return $_!=="";});
$t = array_values($t);
if (count($t)<10) continue;
$device = trim($t[0], ": ");
if ($device == 'lo') continue; //skip localhost
$receive = trim($t[1]);
$transmit = trim($t[9]);
$devices[$device] = [$receive, $transmit];
if (isset($old_devices->$device))
{
$receive -= $old_devices->$device[0];
$transmit -= $old_devices->$device[1];
}
$receive /= $time_diff;
$transmit /= $time_diff;
$dev[$device] = [$receive, $transmit];
}
$out = [];
$max = $min = $sum = [0,0];
foreach ($dev as $key=>$value)
{
$out['interfaces'][$key]['in'] = $value[0];
$out['interfaces'][$key]['out'] = $value[1];
for ($i=0;$i<2;++$i)
{
if ($max[$i]<$value[$i])
$max[$i]=$value[$i];
if ($min[$i]>$value[$i])
$min[$i]=$value[$i];
$sum[$i]+=$value[$i];
}
}
$out['in']['max']=$max[0]; // highest in
$out['out']['max']=$max[1]; // highest out
$out['in']['min']=$min[0]; // lower in
$out['out']['min']=$min[1]; // lowest out
$out['in']['all']=$sum[0]; // total in (all interfaces)
$out['out']['all']=$sum[1];
$out['time_chunk']=$time_diff;
$t = $out;
$out = [];
$out['total'] = $t['out']['all'] + $t['in']['all'];
$out = array_merge($out, $t);
file_put_contents(".last", json_encode([
'time' => microtime(true),
'devices' => $devices
]), LOCK_EX);
return $out;
}
/**
* Disk stats
* @return [type] [description]
*/
function system_stat_disk()
{
$res = shell_exec("df");
$res = explode(PHP_EOL, $res);
foreach ($res as &$r)
$r = array_values(array_filter(explode(" ", $r), function ($_) { return $_!=="";}));
$out = [];
foreach ($res as $r)
{
if ($r[5] != '/') continue; // only meausre root disk
$out['disk'] = $r[0];
$out['used'] = $r[2]*1024;
$out['available'] = $r[3]*1024;
$out['total'] = $r[1]*1024;
}
return $out;
}
/**
* Memory statistics
* @return array
*/
function system_stat_memory()
{
$res = parse_colon_proc("meminfo");
$desired = [
'MemTotal' => 'total',
'MemFree' => 'free',
'MemAvailable' => 'available',
'SwapTotal' => 'swap',
'SwapFree' => 'swap_free',
'SwapAvailable' => 'swap_available',
];
foreach ($res as $k=>$v)
{
if (array_key_exists($k, $desired))
$out[$desired[$k]] = substr($v,0,-2)*1024; // xxx kB
}
return $out;
}
/**
* CPU statistics
* @return array
*/
function system_stat_cpu()
{
$res = parse_colon_proc("cpuinfo");
$desired = [
'cpu cores' => 'cores',
'cpu MHz' => 'MHz',
];
foreach ($res as $k=>$v)
{
if (array_key_exists($k, $desired))
$out[$desired[$k]] = $v;
}
$load = shell_exec('uptime');
$load = substr($load, strpos($load, "load average")+14);
$out['load_1'] = explode(" ", $load)[0]*1;
$out['load_5'] = explode(" ", $load)[1]*1;
$out['load_15'] = explode(" ", $load)[2]*1;
$out['load_percentage'] = sprintf("%.2f", $out['load_1'] * 100 / $out['cores']);
return $out;
}
/**
* Get a system stat, or null
* @param string $type
* @return array|null
*/
function system_stat($type)
{
$func = "system_stat_{$type}";
if (function_exists($func))
return $func();
else
return null;
}
/**
* Aggregate stats
* @return array
*/
function system_stats()
{
$out = [];
$cats = ['memory','cpu','net','socket','disk'];
foreach ($cats as $v)
{
$out[$v] = system_stat($v);
}
$out['time'] = time();
return $out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment