首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP FreeBSD 系統信息採集:CPU、負載、內存、Swap 與運行時間

     編輯:PHP 相關知識

FreeBSD 系統信息來源

FreeBSD 不使用 /proc,而是通過 sysctl 命令獲取內核參數,並結合 vmstat、swapinfo 等工具獲取運行時指標。

完整實現類

<?php
/**
 * FreeBSD 系統信息採集器
 * 需 PHP 有權限執行 sysctl、vmstat、swapinfo 命令
 */
class FreeBsdSysInfo {
    public static function get(): ?array {
        if (stripos(PHP_OS, 'FreeBSD') === false) {
            return null;
        }

        $info = [];

        // CPU
        $info['cpu'] = self::getCpuInfo();

        // 負載
        $info['load'] = self::getLoadAvg();

        // 運行時間
        $info['uptime'] = self::getUptime();

        // 內存
        $info['memory'] = self::getMemoryInfo();

        return $info;
    }

    private static function sysctl(string $key): ?string {
        $cmd = "sysctl -n " . escapeshellarg($key);
        $output = @shell_exec($cmd);
        return $output ? trim($output) : null;
    }

    private static function getCpuInfo(): array {
        $ncpu = self::sysctl('hw.ncpu');
        $model = self::sysctl('hw.model');
        return [
            'cores' => $ncpu ? (int)$ncpu : 0,
            'model' => $model ?: 'Unknown',
        ];
    }

    private static function getLoadAvg(): array {
        $load = self::sysctl('vm.loadavg');
        if (!$load) return ['error' => '無法獲取負載'];

        // 格式:{ 0.52 0.48 0.45 }
        $load = trim($load, '{}');
        $parts = array_map('floatval', explode(' ', $load));
        return [
            '1min' => $parts[0] ?? 0,
            '5min' => $parts[1] ?? 0,
            '15min' => $parts[2] ?? 0,
        ];
    }

    private static function getUptime(): array {
        $boottime = self::sysctl('kern.boottime');
        if (!$boottime) return ['error' => '無法獲取啟動時間'];

        // 格式:{ sec = 1700000000, usec = 123456 } Thu Jan 1 00:00:00 2024
        if (preg_match('/sec\s*=\s*(\d+)/', $boottime, $m)) {
            $bootSec = (int)$m[1];
            $now = time();
            $uptimeSec = $now - $bootSec;
            $days = floor($uptimeSec / 86400);
            $hours = floor(($uptimeSec % 86400) / 3600);
            $minutes = floor(($uptimeSec % 3600) / 60);
            return [
                'seconds' => $uptimeSec,
                'human' => sprintf('%d天 %d小時 %d分鐘', $days, $hours, $minutes),
                'boot_time' => $bootSec,
            ];
        }
        return ['error' => '解析啟動時間失敗'];
    }

    private static function getMemoryInfo(): array {
        // 物理內存
        $physmem = self::sysctl('hw.physmem');
        $totalMem = $physmem ? round($physmem / 1024 / 1024, 2) : 0; // MB

        // vmstat 獲取空閒內存
        $vmstat = @shell_exec('vmstat');
        $freeMem = 0;
        if ($vmstat) {
            $lines = explode("\n", trim($vmstat));
            if (count($lines) >= 3) {
                $fields = preg_split('/\s+/', trim($lines[2]));
                // free 列通常是第 5 欄(0-indexed 4)
                $freeMem = isset($fields[4]) ? round($fields[4] / 1024, 2) : 0; // MB
            }
        }

        // swapinfo 獲取交換分區
        $swapinfo = @shell_exec('swapinfo -k');
        $swap = ['total' => 0, 'used' => 0, 'free' => 0, 'percent' => 0];
        if ($swapinfo) {
            $lines = explode("\n", trim($swapinfo));
            if (count($lines) >= 2) {
                // 跳過標題行
                $fields = preg_split('/\s+/', trim($lines[1]));
                // 1K-blocks Used Avail Capacity
                if (count($fields) >= 4) {
                    $swap['total'] = round($fields[0] / 1024, 2); // MB
                    $swap['used'] = round($fields[1] / 1024, 2);
                    $swap['free'] = round($fields[2] / 1024, 2);
                    $swap['percent'] = $swap['total'] > 0 ? round($swap['used'] / $swap['total'] * 100, 2) : 0;
                }
            }
        }

        $usedMem = $totalMem - $freeMem;
        $memPercent = $totalMem > 0 ? round($usedMem / $totalMem * 100, 2) : 0;

        return [
            'memory' => [
                'total' => $totalMem,
                'free' => $freeMem,
                'used' => $usedMem,
                'percent' => $memPercent,
            ],
            'swap' => $swap,
        ];
    }
}

// 使用示例
$data = FreeBsdSysInfo::get();
if ($data) {
    echo '<pre>';
    print_r($data);
    echo '</pre>';
} else {
    echo '非 FreeBSD 環境';
}
?>

關鍵命令對照表

指標Linux (/proc)FreeBSD (sysctl/命令)
CPU 核心數/proc/cpuinfosysctl hw.ncpu
CPU 型號/proc/cpuinfosysctl hw.model
負載/proc/loadavgsysctl vm.loadavg
啟動時間/proc/uptimesysctl kern.boottime
物理內存/proc/meminfosysctl hw.physmem
空閒內存/proc/meminfovmstat (free 欄)
Swap 信息/proc/meminfoswapinfo -k

部署注意事項

  1. 命令路徑:確保 sysctl、vmstat、swapinfo 在 PHP 的 PATH 中(通常在 /usr/sbin,可能需配置 safe_mode_exec_dir 或使用絕對路徑)。
  2. 權限:PHP-FPM 運行用戶需有執行上述命令權限,或通過 sudoers 免密授權特定命令。
  3. 解析穩健性:命令輸出格式可能因 FreeBSD 版本不同而差異,建議加入版本檢測或多模式解析。
  4. 性能:每次調用執行多個外部命令,Web 面板建議緩存 10-30 秒。

統一接口適配器

若項目同時部署在 Linux 和 FreeBSD,可編寫工廠模式統一調用:

class SysInfoFactory {
    public static function create(): ?SysInfoInterface {
        if (PHP_OS_FAMILY === 'Linux') return new LinuxSysInfo();
        if (stripos(PHP_OS, 'FreeBSD') !== false) return new FreeBsdSysInfo();
        return null;
    }
}

interface SysInfoInterface {
    public static function get(): ?array;
}
// LinuxSysInfo 和 FreeBsdSysInfo 實現此接口
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved