获取 MAC 地址

2024-10-10 08:38:00
admin
原创
78
摘要:问题描述:我需要一种跨平台方法,用于在运行时确定计算机的 MAC 地址。对于 Windows,可以使用“wmi”模块,而我在 Linux 下找到的唯一方法是运行 ifconfig 并在其输出上运行正则表达式。我不喜欢使用仅在一个操作系统上运行的软件包,解析另一个程序的输出似乎不太优雅,更不用说容易出错了。有人...

问题描述:

我需要一种跨平台方法,用于在运行时确定计算机的 MAC 地址。对于 Windows,可以使用“wmi”模块,而我在 Linux 下找到的唯一方法是运行 ifconfig 并在其输出上运行正则表达式。我不喜欢使用仅在一个操作系统上运行的软件包,解析另一个程序的输出似乎不太优雅,更不用说容易出错了。

有人知道跨平台方法(Windows 和 Linux)获取 MAC 地址的方法吗?如果没有,有人知道比我上面列出的更优雅的方法吗?


解决方案 1:

Python 2.5 包含一个 uuid 实现,它(至少在一个版本中)需要 mac 地址。您可以轻松地将 mac 查找函数导入到您自己的代码中:

from uuid import getnode as get_mac
mac = get_mac()

返回值是 48 位整数的 mac 地址。

解决方案 2:

在 Linux 下,获取特定本地接口的 MAC 地址的纯 Python 解决方案,最初由 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()

解决方案 3:

netifaces是一个用于获取 mac 地址(和其他地址)的好模块。它是跨平台的,比使用套接字或 uuid 更有意义。

import netifaces

netifaces.interfaces()
# ['lo', 'eth0', 'tun2']

netifaces.ifaddresses('eth0')[netifaces.AF_LINK]
# [{'addr': '08:00:27:50:f2:51', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]

  • pypi 位置

  • Netifaces 的良好介绍

解决方案 4:

有时我们有多个网络接口。

找出特定接口的 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")

解决方案 5:

您应该注意的另一件事是,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.

解决方案 6:

使用我这里的答案: https: //stackoverflow.com/a/18031868/2362361

由于存在许多 iface(蓝牙、多个 nic 等),因此了解您想要将 MAC 分配给哪个 iface 非常重要。

当您知道需要 MAC 的 iface 的 IP 时,此操作即可完成,使用netifaces(可在 PyPI 中使用):

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'

解决方案 7:

您可以使用跨平台的 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]

解决方案 8:

如果您不介意依赖,跨平台的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),您仍然可以使用该软件包的旧版本。

解决方案 9:

要获取eth0接口 MAC 地址,

import psutil

nics = psutil.net_if_addrs()['eth0']

for interface in nics:
   if interface.family == 17:
      print(interface.address)

解决方案 10:

请注意,您可以使用条件导入在 Python 中构建自己的跨平台库。例如

import platform
if platform.system() == 'Linux':
  import LinuxMac
  mac_address = LinuxMac.get_mac_address()
elif platform.system() == 'Windows':
  # etc

这将允许您使用 os.system 调用或特定于平台的库。

解决方案 11:

很好,实际上返回一个字典,在字典中返回一个列表,在列表中,它返回一个主食。但是nics'Ethernet'.address迭代解决了这个问题。

import psutil

nics = psutil.net_if_addrs()

mac_address = nics['Ethernet'][0].address

print(mac_address)

解决方案 12:

此跨平台代码在 Windows 上并非 100% 有效。以下代码在 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')
]

解决方案 13:

要获取 48 位整数形式的 MAC 地址,可以使用uuid.getnode()

import uuid

uuid.getnode()
12345678901234

要将其格式化为冒号分隔的十六进制字符串,您可以使用

":".join(f"{b:02x}" for b in uuid.getnode().to_bytes(6))
0b:3a:73:ce:2f:f2

(在 Python 3.10 及更低版本中,您必须添加byteorderarg: .to_bytes(6, byteorder='big')。)

解决方案 14:

我不知道有没有统一的方法,但是你可能会发现这里有一些有用的东西:

http://www.codeguru.com/Cpp/IN/network/networkinformation/article.php/c5451

在这种情况下,我会将这些包装成一个函数,并根据操作系统运行正确的命令,根据需要进行解析,并仅返回按您想要的格式显示的 MAC 地址。当然,一切都一样,只是您只需执行一次,而且从主代码来看,它看起来更简洁。

解决方案 15:

或者,

import uuid
mac_id=(':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff)

解决方案 16:

对于 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(暂时,重启后将恢复为实际地址)。

解决方案 17:

对于 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。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用