2008-10-01 4 views
85

Мне нужен кросс-платформенный метод определения MAC-адреса компьютера во время выполнения. Для окон можно использовать модуль «wmi», и единственным методом под Linux, который я смог найти, было запустить ifconfig и запустить регулярное выражение на его выходе. Мне не нравится использовать пакет, который работает только на одной ОС, и анализ вывода другой программы не выглядит очень элегантным, не говоря уже о склонности к ошибкам.Получение MAC-адреса

Кто-нибудь знает метод перекрестной платформы (windows и linux) для получения MAC-адреса? Если нет, кто-нибудь знает какие-либо более элегантные методы, чем те, которые я перечислял выше?

ответ

123

Python 2.5 включает в себя реализацию uuid, которая (по меньшей мере, одной версии) нуждается в адресе mac. Вы можете импортировать макинтош найти функцию в свой собственный код легко:

from uuid import getnode as get_mac 
mac = get_mac() 

Возвращаемое значение является MAC-адрес, как 48 битное целое число.

+16

Я просто попробовал это на коробке Windows, и он отлично работает ... кроме того, что ноутбук, на котором я его пробовал, имеет 2 сетевых адаптера (один беспроводной), и нет способа определить, какой MAC он вернул. Просто слово предупреждения, если вы хотите использовать этот код. – technomalogical 2008-10-01 19:55:45

+1

Это функция перечислителя устройств Windows, независимо от того, какой метод вы используете для получения адреса - вы должны быть осторожны, если используете его как уникальный идентификатор. – 2008-10-01 22:12:15

+15

Просто предупреждение: если вы посмотрите на документацию `getnode`, то это говорит о том, что он будет возвращать случайный длинный, если он не сможет обнаружить макрос:« Если все попытки получить аппаратный адрес не сработают, выберите случайный 48-битный номер с восьмым битом, установленным в 1, как рекомендовано в RFC 4122. " Поэтому проверьте, что восьмой бит! – deinonychusaur 2013-02-01 11:27:00

19

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'}] 

+0

Используется лично, для каждой системы требуется определенная установка/компиляция, но работает хорошо. – Aatch 2011-06-20 17:10:58

1

Я не знаю единообразно, но Heres то, что вы могли бы оказаться полезными:

http://www.codeguru.com/Cpp/I-N/network/networkinformation/article.php/c5451

Что бы я делал в этом случае, это было бы превратить их в функцию, и на основе ОС она выполнит правильную команду, проанализирует по мере необходимости и вернет только MAC-адрес, отформатированный так, как вы хотите. Конечно, все это, за исключением того, что вам нужно сделать это только один раз, и он выглядит более чистым от основного кода.

-6

Для Linux вы можете получить MAC-адрес с помощью SIOCGIFHWADDR ioctl.

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.

3

Обратите внимание, что вы можете создать свою собственную кросс-платформенную библиотеку в python с использованием условного импорта. например

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

Это позволит вам использовать вызовы os.system или библиотеки, специфичные для платформы.

19

Еще одна вещь, которую вы должны отметить, заключается в том, что uuid.getnode() может подделывать MAC-адрес, возвращая случайное 48-битное число, которое может и не быть тем, что вы ожидаете. Кроме того, нет явного указания на то, что 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. 
70

Чистый питон решение этой проблемы под Linux, чтобы получить MAC для конкретного локального интерфейса, первоначально размещен как комментарий по vishnubob и усовершенствован на Бен Макки в this activestate recipe

#!/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') 
2

для Linux позвольте мне представить сценарий оболочки, который покажет MAC-адрес и позволит его изменить (обнюхивание MAC).

ifconfig eth0 | grep HWaddr |cut -dH -f2|cut -d\ -f2 
00:26:6c:df:c3:95 

Cut могут dffer заданы параметры (я не эксперт) попробовать:

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 (временно, после перезагрузки он будет восстановлен до фактического).

8

Используя мой ответ здесь: https://stackoverflow.com/a/18031868/2362361

Было бы важно знать, к которому Iface вы хотите MAC для многих, так как может существовать (Bluetooth, несколько сетевых карт и т.д.).

Это делает работу, когда вы знаете IP в IFACE вам понадобится MAC для, используя 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 

Testing:

>>> mac_for_ip('169.254.90.191') 
'2c:41:38:0a:94:8b' 
-1

для решения Linux

INTERFACE_NAME = "eth0" 

####################################### 
def get_mac_id(ifname=INTERFACE_NAME): 

import commands 

words = commands.getoutput("ifconfig " + ifname).split() 
if "HWaddr" in words: 
    return words[ words.index("HWaddr") + 1 ] 
else: 
    return 'No MAC Address Found!' 

Использование:

print get_mac_id(ifname="eth0") 
11

Иногда у нас имеется более одного сетевого интерфейса.

Простой метод, чтобы узнать 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") 
1

Вы можете сделать это с psutil, который кросс- платформа:

import psutil 

mac_addresses = [] 

nics = psutil.net_if_addrs() 
nics.pop('lo') # remove loopback since it doesnt have a real mac address 

for i in nics: 
    for j in nics[i]: 
     if j.family == 17: # AF_LINK 
      mac_addresses.append(j.address) 
Смежные вопросы