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

PHP 獲取服務器網卡 MAC 地址的跨平台實現類

     編輯:PHP 綜合知識

PHP 獲取服務器 MAC 地址:Windows/Linux 跨平台實現類

在軟件授權綁定、設備指紋識別、集群節點識別等場景中,需要獲取服務器網卡的物理 MAC 地址。本文提供一個支援 Windows (ipconfig) 和 Linux (ifconfig/ip) 的 PHP 類,通過解析系統命令輸出提取 MAC 地址。

核心實現類

<?php
class GetMacAddr {
    private $returnArray = [];
    private $macAddr = '';

    /**
     * 構造函數自動檢測系統並獲取 MAC
     * @param string $osType PHP_OS 常量或自定義標識
     * @return string MAC 地址或空字符串
     */
    public function __construct($osType = PHP_OS) {
        switch (strtolower($osType)) {
            case 'linux':
            case 'unix':
            case 'freebsd':
            case 'darwin':  // macOS
                $this->forLinux();
                break;
            case 'winnt':
            case 'windows':
            case 'cygwin':
                $this->forWindows();
                break;
            default:
                // 嘗試 Linux 命令作為兜底
                $this->forLinux();
                break;
        }
        $this->extractMac();
    }

    // Linux/Unix: ifconfig -a 或 ip link
    private function forLinux() {
        // 優先使用 ip 命令(現代發行版),回退 ifconfig
        @exec("ip link show 2>/dev/null", $this->returnArray);
        if (empty($this->returnArray)) {
            @exec("ifconfig -a 2>/dev/null", $this->returnArray);
        }
    }

    // Windows: ipconfig /all
    private function forWindows() {
        @exec("ipconfig /all 2>nul", $this->returnArray);
        if (empty($this->returnArray)) {
            $sysDir = getenv('SystemRoot') . '\\System32';
            @exec("{$sysDir}\\ipconfig.exe /all 2>nul", $this->returnArray);
        }
    }

    // 從命令輸出中提取 MAC 地址(正則匹配)
    private function extractMac() {
        $pattern = '/([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}/';
        foreach ($this->returnArray as $line) {
            if (preg_match($pattern, $line, $matches)) {
                // 過濾掉 00:00:00:00:00:00 和 ff:ff:ff:ff:ff:ff
                $mac = strtolower($matches[0]);
                if ($mac !== '00:00:00:00:00:00' && $mac !== 'ff:ff:ff:ff:ff:ff') {
                    $this->macAddr = $mac;
                    break;
                }
            }
        }
    }

    public function getMac() {
        return $this->macAddr;
    }

    public function getAllOutput() {
        return $this->returnArray;
    }
}

// 使用示例
$mac = new GetMacAddr();
echo "MAC: " . $mac->getMac();  // 如 00:1a:2b:3c:4d:5e

命令輸出樣本與正則解析

Linux ip link show

1: lo:  mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0:  mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:1a:2b:3c:4d:5e brd ff:ff:ff:ff:ff:ff

正則匹配 link/ether 後的地址。

Linux ifconfig -a

eth0: flags=4163  mtu 1500
        inet 192.168.1.100  netmask 255.255.255.0  broadcast 192.168.1.255
        ether 00:1a:2b:3c:4d:5e  txqueuelen 1000  (Ethernet)

匹配 ether 後的地址。

Windows ipconfig /all

Windows IP Configuration

Ethernet adapter Ethernet0:
   Physical Address. . . . . . . . . : 00-1A-2B-3C-4D-5E
   IPv4 Address. . . . . . . . . . . : 192.168.1.100

匹配 Physical Address 後的地址(連字符分隔)。

關鍵改進點(對比原代碼)

  • 支援 macOS (Darwin):同屬 Unix 族,用 ifconfig/ip
  • 優先使用 ip link:ifconfig 在部分精簡系統(Alpine、容器)中缺失
  • 過濾無效 MAC:全零、全 F、本地回環地址
  • 大小寫統一:返回小寫冒號格式 aa:bb:cc:dd:ee:ff
  • 錯誤輸出重定向:2>/dev/null / 2>nul 抑制 stderr

權限與環境要求

環境要求
PHP 配置disable_functions 不包含 exec/shell_exec
安全模式safe_mode = Off (PHP 5.4+ 已移除)
容器/Docker需 --cap-add=NET_ADMIN 或宿主網絡模式 --network host
最小權限Web 用戶需可執行 ipconfig/ifconfig/ip

現代化替代:純 PHP 讀取 /sys/class/net (Linux)

<?php
function getMacLinuxSysfs() {
    $netDir = '/sys/class/net';
    if (!is_dir($netDir)) return '';
    
    foreach (scandir($netDir) as $iface) {
        if ($iface === 'lo' || $iface[0] === '.') continue;
        $addrFile = "$netDir/$iface/address";
        if (is_readable($addrFile)) {
            $mac = trim(file_get_contents($addrFile));
            if ($mac !== '00:00:00:00:00:00') {
                return $mac;
            }
        }
    }
    return '';
}
✅ 無需 exec、無命令注入風險、容器友好、性能極高,Linux 專用首選方案。

多網卡場景處理建議

  • 返回所有非回環網卡 MAC 陣列,由業務層決定使用哪張(如綁定第一張物理網卡)
  • 結合 ip route get 8.8.8.8 獲取默認路由網卡,提取對應 MAC
  • 授權綁定建議:MAC + CPU ID + 磁盤序列號 多因子指紋
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved