应使用 net_get_interfaces() 获取本地所有IP,PHP 7.2+ 原生支持,可遍历网卡提取 addr 和 addr6 并过滤回环地址;低版本可用 exec() 调用系统命令并正则解析,需适配不同平台格式并过滤无效IP;容器或云环境受网络命名空间限制,实际获取的IP取决于运行时环境。

gethostbyname() 和 gethostbyaddr() 都不行,别试了
这两个函数只处理主机名与单个 IPv4 地址的映射,gethostbyname('localhost') 返回的永远是 127.0.0.1,哪怕你本机有 192.168.1.100、10.0.0.5、172.16.0.12 三个活跃网卡 IP,它也看不到。想靠它们枚举本地所有 IP,注定失败。
用 net_get_interfaces() 获取全部网卡及对应地址
PHP 7.2+ 原生支持 net_get_interfaces(),它返回关联数组,键为网卡名(如 lo、eth0、wlan0),值为该接口的地址信息数组。关键点:
- 每个接口下可能有多个
addr(IPv4)、addr6(IPv6),需分别提取 -
addr字段存在才表示该接口启用了 IPv4;有些接口只有addr6 - 忽略
127.0.0.1和::1(除非你真需要回环)
示例代码片段:
$interfaces = net_get_interfaces();
$ips = [];
foreach ($interfaces as $name => $iface) {
if (!empty($iface['addr'])) {
if ($iface['addr'] !== '127.0.0.1') {
$ips[] = $iface['addr'];
}
}
if (!empty($iface['addr6'])) {
if ($iface['addr6'] !== '::1') {
$ips[] = $iface['addr6'];
}
}
}
print_r($ips);
PHP 版本低于 7.2?改用 exec() 调系统命令
Linux/macOS 下可用 ip -4 addr show 或 ifconfig(后者在新版系统可能被弃用);Windows 下必须用 ipconfig。注意三点:
立即学习“PHP免费学习笔记(深入)”;
-
exec()可能被禁用(查看disable_functions是否含它) - 不同系统输出格式差异大,正则要适配——Linux 用
/inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\//,Windows 用/IPv4 Address[.\s]*?:\s*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/i - 务必过滤掉
127.0.0.1、0.0.0.0、空行和无效匹配
Linux 简单示例:
$output = [];
exec('ip -4 addr show | grep "inet " | awk \'{print $2}\' | cut -d/ -f1', $output);
$ips = array_filter($output, function($ip) {
return filter_var($ip, FILTER_VALIDATE_IP) && $ip !== '127.0.0.1';
});
别忘了 Docker 容器或云主机的特殊网络层
在容器里跑 PHP,net_get_interfaces() 返回的是容器网络命名空间里的接口(比如只有 lo 和 eth0,IP 是内网地址);云主机(如阿里云 ECS)可能绑定多个弹性网卡,但默认只显示主网卡。这时候:
- 查
/sys/class/net/目录是否存在额外网卡名(如eth1、ens3) - 手动读取
/sys/class/net/{iface}/address(MAC)和/sys/class/net/{iface}/device/判断是否为真实网卡 - 某些云平台提供元数据服务(如
http://100.100.100.200/latest/meta-data/network/interfaces/macs/),需 HTTP 请求获取
纯 PHP 没法绕过容器隔离或云平台限制——看到什么 IP,取决于你运行时所处的网络命名空间。











