[英]Getting MAC Address
我需要一种在运行时确定计算机 MAC 地址的跨平台方法。 对于 windows,可以使用“wmi”模块,在 Linux 下,我能找到的唯一方法是运行 ifconfig 并在其 output 上运行正则表达式。我不喜欢使用仅适用于一个操作系统的 package,并解析 output另一个程序似乎不太优雅,更不用说容易出错了。
有谁知道获取MAC地址的跨平台方法(windows和linux)方法? 如果没有,有没有人知道比我上面列出的方法更优雅的方法?
Python 2.5 包含一个 uuid 实现,它(至少在一个版本中)需要 mac 地址。 您可以轻松地将 mac 查找功能导入到您自己的代码中:
from uuid import getnode as get_mac
mac = get_mac()
返回值为 48 位整数的 mac 地址。
Linux 下此问题的纯 python 解决方案,用于获取特定本地接口的 MAC,最初由 vishnubob 作为评论发布,并由 Ben Mackey 在此 activestate 配方中改进
#!/usr/bin/python
import fcntl, socket, struct
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
return ':'.join(['%02x' % ord(char) for char in info[18:24]])
print getHwAddr('eth0')
这是 Python 3 兼容的代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import fcntl
import socket
import struct
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15]))
return ':'.join('%02x' % b for b in info[18:24])
def main():
print(getHwAddr('enp0s8'))
if __name__ == "__main__":
main()
有时我们有不止一个网络接口。
找出特定接口的mac地址的简单方法是:
def getmac(interface):
try:
mac = open('/sys/class/net/'+interface+'/address').readline()
except:
mac = "00:00:00:00:00:00"
return mac[0:17]
调用方法很简单
myMAC = getmac("wlan0")
您应该注意的另一件事是uuid.getnode()
可以通过返回一个随机的 48 位数字来伪造 MAC 地址,这可能不是您所期望的。 此外,没有明确指示 MAC 地址已被伪造,但您可以通过调用getnode()
两次并查看结果是否变化来检测它。 如果两个调用都返回相同的值,则您拥有 MAC 地址,否则您将获得伪造的地址。
>>> print uuid.getnode.__doc__
Get the hardware address as a 48-bit positive integer.
The first time this runs, it may launch a separate program, which could
be quite slow. If all attempts to obtain the hardware address fail, we
choose a random 48-bit number with its eighth bit set to 1 as recommended
in RFC 4122.
使用我的回答: https ://stackoverflow.com/a/18031868/2362361
重要的是要知道您想要 MAC 用于哪个接口,因为可以存在许多接口(蓝牙、多个 nic 等)。
当您使用netifaces
(在 PyPI 中可用)知道需要 MAC 的 iface 的 IP 时,这可以完成工作:
import netifaces as nif
def mac_for_ip(ip):
'Returns a list of MACs for interfaces that have given IP, returns None if not found'
for i in nif.interfaces():
addrs = nif.ifaddresses(i)
try:
if_mac = addrs[nif.AF_LINK][0]['addr']
if_ip = addrs[nif.AF_INET][0]['addr']
except IndexError, KeyError: #ignore ifaces that dont have MAC or IP
if_mac = if_ip = None
if if_ip == ip:
return if_mac
return None
测试:
>>> mac_for_ip('169.254.90.191')
'2c:41:38:0a:94:8b'
您可以使用跨平台的 psutil 执行此操作:
import psutil
nics = psutil.net_if_addrs()
print [j.address for j in nics[i] for i in nics if i!="lo" and j.family==17]
请注意,您可以使用条件导入在 python 中构建自己的跨平台库。 例如
import platform
if platform.system() == 'Linux':
import LinuxMac
mac_address = LinuxMac.get_mac_address()
elif platform.system() == 'Windows':
# etc
这将允许您使用 os.system 调用或特定于平台的库。
如果您不介意依赖依赖,跨平台的getmac包将适用于此。 它适用于 Python 2.7+ 和 3.4+。 它将尝试许多不同的方法,直到获得地址或返回 None。
from getmac import get_mac_address
eth_mac = get_mac_address(interface="eth0")
win_mac = get_mac_address(interface="Ethernet 3")
ip_mac = get_mac_address(ip="192.168.0.1")
ip6_mac = get_mac_address(ip6="::1")
host_mac = get_mac_address(hostname="localhost")
updated_mac = get_mac_address(ip="10.0.0.1", network_request=True)
免责声明:我是包的作者。
更新(2019 年 1 月 14 日):该包现在仅支持 Python 2.7+ 和 3.4+。 如果您需要使用较旧的 Python(2.5、2.6、3.2、3.3),您仍然可以使用较旧版本的包。
要获取eth0
接口 MAC 地址,
import psutil
nics = psutil.net_if_addrs()['eth0']
for interface in nics:
if interface.family == 17:
print(interface.address)
nice实际上在字典中返回一个字典,它返回一个列表,在列表中,它返回一个订书钉。 但是nics['Ethernet'][0].address迭代解决了这个问题。
import psutil
nics = psutil.net_if_addrs()
mac_address = nics['Ethernet'][0].address
print(mac_address)
我不知道统一的方式,但这里有一些你可能会觉得有用的东西:
http://www.codeguru.com/Cpp/IN/network/networkinformation/article.php/c5451
在这种情况下,我要做的是将它们包装成一个函数,并根据操作系统运行正确的命令,根据需要进行解析并仅返回您想要格式化的 MAC 地址。 它当然都是一样的,除了你只需要做一次,而且从主代码看起来更干净。
此跨平台代码并非 100% 适用于 Windows。这适用于 Windows:
import psutil
print([(k, addr.address) for k, v in psutil.net_if_addrs().items() for addr in v if addr.family == -1])
例子:
[
('Local Area Connection', '01-23-45-67-89-0A'),
('Wireless Network Connection', '23-45-67-89-0A-BC'),
('Bluetooth Network Connection', '45-67-89-0A-BC-DE'),
('isatap.{01ABCDEF-0123-4567-890A-0123456789AB}', '00-00-00-00-00-00-00-01')
]
或者,
import uuid
mac_id=(':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff)
对于 Linux,让我介绍一个 shell 脚本,它将显示 mac 地址并允许更改它(MAC 嗅探)。
ifconfig eth0 | grep HWaddr |cut -dH -f2|cut -d\ -f2
00:26:6c:df:c3:95
削减争论可能会有所不同(我不是专家)尝试:
ifconfig etho | grep HWaddr
eth0 Link encap:Ethernet HWaddr 00:26:6c:df:c3:95
要更改 MAC,我们可以这样做:
ifconfig eth0 down
ifconfig eth0 hw ether 00:80:48:BA:d1:30
ifconfig eth0 up
将 mac 地址更改为 00:80:48:BA:d1:30 (暂时,将在重新启动时恢复为实际地址)。
对于 Linux,您可以使用 SIOCGIFHWADDR ioctl 检索 MAC 地址。
struct ifreq ifr;
uint8_t macaddr[6];
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
return -1;
strcpy(ifr.ifr_name, "eth0");
if (ioctl(s, SIOCGIFHWADDR, (void *)&ifr) == 0) {
if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6);
return 0;
... etc ...
您已将问题标记为“python”。 我不知道现有的 Python 模块可以获取此信息。 您可以使用ctypes直接调用 ioctl。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.