1*1d05cddcSAtari911<?php 2*1d05cddcSAtari911/** 3*1d05cddcSAtari911 * System Stats API Endpoint 4*1d05cddcSAtari911 * Returns real-time CPU and memory usage 5*1d05cddcSAtari911 */ 6*1d05cddcSAtari911 7*1d05cddcSAtari911header('Content-Type: application/json'); 8*1d05cddcSAtari911header('Cache-Control: no-cache, must-revalidate'); 9*1d05cddcSAtari911 10*1d05cddcSAtari911$stats = [ 11*1d05cddcSAtari911 'cpu' => 0, 12*1d05cddcSAtari911 'cpu_5min' => 0, 13*1d05cddcSAtari911 'memory' => 0, 14*1d05cddcSAtari911 'timestamp' => time(), 15*1d05cddcSAtari911 'load' => ['1min' => 0, '5min' => 0, '15min' => 0], 16*1d05cddcSAtari911 'uptime' => '', 17*1d05cddcSAtari911 'memory_details' => [], 18*1d05cddcSAtari911 'top_processes' => [] 19*1d05cddcSAtari911]; 20*1d05cddcSAtari911 21*1d05cddcSAtari911// Get CPU usage and load averages 22*1d05cddcSAtari911if (function_exists('sys_getloadavg')) { 23*1d05cddcSAtari911 $load = sys_getloadavg(); 24*1d05cddcSAtari911 if ($load !== false) { 25*1d05cddcSAtari911 // Use 1-minute load average for real-time feel 26*1d05cddcSAtari911 // Normalize to percentage (assuming max load of 2.0 = 100%) 27*1d05cddcSAtari911 $stats['cpu'] = min(100, ($load[0] / 2.0) * 100); 28*1d05cddcSAtari911 29*1d05cddcSAtari911 // 5-minute average for green bar 30*1d05cddcSAtari911 $stats['cpu_5min'] = min(100, ($load[1] / 2.0) * 100); 31*1d05cddcSAtari911 32*1d05cddcSAtari911 // Store all three load averages for tooltip 33*1d05cddcSAtari911 $stats['load'] = [ 34*1d05cddcSAtari911 '1min' => round($load[0], 2), 35*1d05cddcSAtari911 '5min' => round($load[1], 2), 36*1d05cddcSAtari911 '15min' => round($load[2], 2) 37*1d05cddcSAtari911 ]; 38*1d05cddcSAtari911 } 39*1d05cddcSAtari911} 40*1d05cddcSAtari911 41*1d05cddcSAtari911// Get memory usage 42*1d05cddcSAtari911if (stristr(PHP_OS, 'linux')) { 43*1d05cddcSAtari911 // Linux: Read from /proc/meminfo 44*1d05cddcSAtari911 $meminfo = file_get_contents('/proc/meminfo'); 45*1d05cddcSAtari911 if ($meminfo) { 46*1d05cddcSAtari911 preg_match('/MemTotal:\s+(\d+)/', $meminfo, $total); 47*1d05cddcSAtari911 preg_match('/MemAvailable:\s+(\d+)/', $meminfo, $available); 48*1d05cddcSAtari911 49*1d05cddcSAtari911 if (isset($total[1]) && isset($available[1])) { 50*1d05cddcSAtari911 $totalMem = $total[1]; 51*1d05cddcSAtari911 $availableMem = $available[1]; 52*1d05cddcSAtari911 $usedMem = $totalMem - $availableMem; 53*1d05cddcSAtari911 $stats['memory'] = ($usedMem / $totalMem) * 100; 54*1d05cddcSAtari911 } 55*1d05cddcSAtari911 } 56*1d05cddcSAtari911} elseif (stristr(PHP_OS, 'darwin') || stristr(PHP_OS, 'bsd')) { 57*1d05cddcSAtari911 // macOS/BSD: Use vm_stat 58*1d05cddcSAtari911 $vm_stat = shell_exec('vm_stat'); 59*1d05cddcSAtari911 if ($vm_stat) { 60*1d05cddcSAtari911 preg_match('/Pages free:\s+(\d+)\./', $vm_stat, $free); 61*1d05cddcSAtari911 preg_match('/Pages active:\s+(\d+)\./', $vm_stat, $active); 62*1d05cddcSAtari911 preg_match('/Pages inactive:\s+(\d+)\./', $vm_stat, $inactive); 63*1d05cddcSAtari911 preg_match('/Pages wired down:\s+(\d+)\./', $vm_stat, $wired); 64*1d05cddcSAtari911 65*1d05cddcSAtari911 if (isset($free[1], $active[1], $inactive[1], $wired[1])) { 66*1d05cddcSAtari911 $pageSize = 4096; // bytes 67*1d05cddcSAtari911 $totalPages = $free[1] + $active[1] + $inactive[1] + $wired[1]; 68*1d05cddcSAtari911 $usedPages = $active[1] + $inactive[1] + $wired[1]; 69*1d05cddcSAtari911 70*1d05cddcSAtari911 if ($totalPages > 0) { 71*1d05cddcSAtari911 $stats['memory'] = ($usedPages / $totalPages) * 100; 72*1d05cddcSAtari911 } 73*1d05cddcSAtari911 } 74*1d05cddcSAtari911 } 75*1d05cddcSAtari911} elseif (stristr(PHP_OS, 'win')) { 76*1d05cddcSAtari911 // Windows: Use wmic 77*1d05cddcSAtari911 $wmic = shell_exec('wmic OS get FreePhysicalMemory,TotalVisibleMemorySize /Value'); 78*1d05cddcSAtari911 if ($wmic) { 79*1d05cddcSAtari911 preg_match('/FreePhysicalMemory=(\d+)/', $wmic, $free); 80*1d05cddcSAtari911 preg_match('/TotalVisibleMemorySize=(\d+)/', $wmic, $total); 81*1d05cddcSAtari911 82*1d05cddcSAtari911 if (isset($free[1]) && isset($total[1])) { 83*1d05cddcSAtari911 $freeMem = $free[1]; 84*1d05cddcSAtari911 $totalMem = $total[1]; 85*1d05cddcSAtari911 $usedMem = $totalMem - $freeMem; 86*1d05cddcSAtari911 $stats['memory'] = ($usedMem / $totalMem) * 100; 87*1d05cddcSAtari911 } 88*1d05cddcSAtari911 } 89*1d05cddcSAtari911} 90*1d05cddcSAtari911 91*1d05cddcSAtari911// Fallback: Use PHP memory if system memory unavailable 92*1d05cddcSAtari911if ($stats['memory'] == 0) { 93*1d05cddcSAtari911 $memLimit = ini_get('memory_limit'); 94*1d05cddcSAtari911 if ($memLimit != '-1') { 95*1d05cddcSAtari911 $memLimitBytes = return_bytes($memLimit); 96*1d05cddcSAtari911 $memUsage = memory_get_usage(true); 97*1d05cddcSAtari911 $stats['memory'] = ($memUsage / $memLimitBytes) * 100; 98*1d05cddcSAtari911 } 99*1d05cddcSAtari911} 100*1d05cddcSAtari911 101*1d05cddcSAtari911// Get uptime (Linux/Unix) 102*1d05cddcSAtari911if (file_exists('/proc/uptime')) { 103*1d05cddcSAtari911 $uptime = file_get_contents('/proc/uptime'); 104*1d05cddcSAtari911 if ($uptime) { 105*1d05cddcSAtari911 $uptimeSeconds = floatval(explode(' ', $uptime)[0]); 106*1d05cddcSAtari911 $days = floor($uptimeSeconds / 86400); 107*1d05cddcSAtari911 $hours = floor(($uptimeSeconds % 86400) / 3600); 108*1d05cddcSAtari911 $minutes = floor(($uptimeSeconds % 3600) / 60); 109*1d05cddcSAtari911 $stats['uptime'] = sprintf('%dd %dh %dm', $days, $hours, $minutes); 110*1d05cddcSAtari911 } 111*1d05cddcSAtari911} elseif (stristr(PHP_OS, 'win')) { 112*1d05cddcSAtari911 // Windows uptime 113*1d05cddcSAtari911 $wmic = shell_exec('wmic os get lastbootuptime'); 114*1d05cddcSAtari911 if ($wmic && preg_match('/(\d{14})/', $wmic, $matches)) { 115*1d05cddcSAtari911 $bootTime = DateTime::createFromFormat('YmdHis', $matches[1]); 116*1d05cddcSAtari911 $now = new DateTime(); 117*1d05cddcSAtari911 $diff = $now->diff($bootTime); 118*1d05cddcSAtari911 $stats['uptime'] = sprintf('%dd %dh %dm', $diff->days, $diff->h, $diff->i); 119*1d05cddcSAtari911 } 120*1d05cddcSAtari911} 121*1d05cddcSAtari911 122*1d05cddcSAtari911// Get detailed memory info (Linux) 123*1d05cddcSAtari911if (stristr(PHP_OS, 'linux') && file_exists('/proc/meminfo')) { 124*1d05cddcSAtari911 $meminfo = file_get_contents('/proc/meminfo'); 125*1d05cddcSAtari911 if ($meminfo) { 126*1d05cddcSAtari911 preg_match('/MemTotal:\s+(\d+)/', $meminfo, $total); 127*1d05cddcSAtari911 preg_match('/MemAvailable:\s+(\d+)/', $meminfo, $available); 128*1d05cddcSAtari911 preg_match('/MemFree:\s+(\d+)/', $meminfo, $free); 129*1d05cddcSAtari911 preg_match('/Buffers:\s+(\d+)/', $meminfo, $buffers); 130*1d05cddcSAtari911 preg_match('/Cached:\s+(\d+)/', $meminfo, $cached); 131*1d05cddcSAtari911 132*1d05cddcSAtari911 if (isset($total[1])) { 133*1d05cddcSAtari911 $totalMB = round($total[1] / 1024, 1); 134*1d05cddcSAtari911 $availableMB = isset($available[1]) ? round($available[1] / 1024, 1) : 0; 135*1d05cddcSAtari911 $usedMB = round(($total[1] - ($available[1] ?? $free[1] ?? 0)) / 1024, 1); 136*1d05cddcSAtari911 $buffersMB = isset($buffers[1]) ? round($buffers[1] / 1024, 1) : 0; 137*1d05cddcSAtari911 $cachedMB = isset($cached[1]) ? round($cached[1] / 1024, 1) : 0; 138*1d05cddcSAtari911 139*1d05cddcSAtari911 $stats['memory_details'] = [ 140*1d05cddcSAtari911 'total' => $totalMB . ' MB', 141*1d05cddcSAtari911 'used' => $usedMB . ' MB', 142*1d05cddcSAtari911 'available' => $availableMB . ' MB', 143*1d05cddcSAtari911 'buffers' => $buffersMB . ' MB', 144*1d05cddcSAtari911 'cached' => $cachedMB . ' MB' 145*1d05cddcSAtari911 ]; 146*1d05cddcSAtari911 } 147*1d05cddcSAtari911 } 148*1d05cddcSAtari911} 149*1d05cddcSAtari911 150*1d05cddcSAtari911// Get top 5 processes by CPU (Linux/Unix) 151*1d05cddcSAtari911if (stristr(PHP_OS, 'linux') || stristr(PHP_OS, 'darwin')) { 152*1d05cddcSAtari911 $ps = shell_exec('ps aux --sort=-%cpu | head -6 | tail -5 2>/dev/null'); 153*1d05cddcSAtari911 if (!$ps) { 154*1d05cddcSAtari911 // Try BSD/macOS format 155*1d05cddcSAtari911 $ps = shell_exec('ps aux -r | head -6 | tail -5 2>/dev/null'); 156*1d05cddcSAtari911 } 157*1d05cddcSAtari911 if ($ps) { 158*1d05cddcSAtari911 $lines = explode("\n", trim($ps)); 159*1d05cddcSAtari911 foreach ($lines as $line) { 160*1d05cddcSAtari911 if (empty($line)) continue; 161*1d05cddcSAtari911 $parts = preg_split('/\s+/', $line, 11); 162*1d05cddcSAtari911 if (count($parts) >= 11) { 163*1d05cddcSAtari911 $stats['top_processes'][] = [ 164*1d05cddcSAtari911 'cpu' => $parts[2] . '%', 165*1d05cddcSAtari911 'mem' => $parts[3] . '%', 166*1d05cddcSAtari911 'command' => substr($parts[10], 0, 30) 167*1d05cddcSAtari911 ]; 168*1d05cddcSAtari911 } 169*1d05cddcSAtari911 } 170*1d05cddcSAtari911 } 171*1d05cddcSAtari911} elseif (stristr(PHP_OS, 'win')) { 172*1d05cddcSAtari911 // Windows top processes 173*1d05cddcSAtari911 $wmic = shell_exec('wmic process get Caption,KernelModeTime /format:csv | findstr /V "^$" | sort /R /+1 | more +1 | findstr /N "^" | findstr "^[1-5]:"'); 174*1d05cddcSAtari911 if ($wmic) { 175*1d05cddcSAtari911 $lines = explode("\n", trim($wmic)); 176*1d05cddcSAtari911 foreach ($lines as $line) { 177*1d05cddcSAtari911 if (preg_match('/^\d+:(.+),(.+),(\d+)/', $line, $matches)) { 178*1d05cddcSAtari911 $stats['top_processes'][] = [ 179*1d05cddcSAtari911 'command' => substr($matches[2], 0, 30), 180*1d05cddcSAtari911 'cpu' => '-' 181*1d05cddcSAtari911 ]; 182*1d05cddcSAtari911 } 183*1d05cddcSAtari911 } 184*1d05cddcSAtari911 } 185*1d05cddcSAtari911} 186*1d05cddcSAtari911 187*1d05cddcSAtari911echo json_encode($stats); 188*1d05cddcSAtari911 189*1d05cddcSAtari911function return_bytes($val) { 190*1d05cddcSAtari911 $val = trim($val); 191*1d05cddcSAtari911 $last = strtolower($val[strlen($val)-1]); 192*1d05cddcSAtari911 $val = (int)$val; 193*1d05cddcSAtari911 switch($last) { 194*1d05cddcSAtari911 case 'g': 195*1d05cddcSAtari911 $val *= 1024; 196*1d05cddcSAtari911 case 'm': 197*1d05cddcSAtari911 $val *= 1024; 198*1d05cddcSAtari911 case 'k': 199*1d05cddcSAtari911 $val *= 1024; 200*1d05cddcSAtari911 } 201*1d05cddcSAtari911 return $val; 202*1d05cddcSAtari911} 203