Отримання MAC-адреси


111

Мені потрібен метод крос-платформи визначення MAC-адреси комп’ютера під час виконання. Для Windows модуль 'wmi' можна використовувати, і єдиний метод під Linux, який я міг знайти, це запустити ifconfig і запустити регулярний вираз по всьому його виводу. Мені не подобається використовувати пакет, який працює лише на одній ОС, і аналіз результатів іншої програми не здається дуже елегантним, не кажучи вже про схильні до помилок.

Хтось знає метод крос-платформи (Windows та Linux), щоб отримати MAC-адресу? Якщо ні, чи хтось знає більш елегантні методи, ніж ті, які я перераховував вище?


Тут є багато потенційно корисних відповідей! Як я можу отримати IP-адресу eth0 в Python?
uhoh

Відповіді:


160

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

from uuid import getnode as get_mac
mac = get_mac()

Повертається значення - mac-адреса як 48-бітове ціле число.


25
Я просто спробував це на вікні Windows, і він чудово працює ... за винятком того, що ноутбук, на який я його випробував, має 2 NIC (один бездротовий) і немає способу визначити, на який MAC він повернувся. Просто слово попередження, якщо ви хочете використовувати цей код.
техномалогічний

24
Просто попередження: Якщо ви подивитесь на getnodeдокументацію, вона говорить про те, що вона повернеться випадково довгий час, якщо не вдасться визначити mac: "Якщо всі спроби отримати апаратну адресу не вдаються, ми вибираємо випадкове 48-бітове число з його восьмим бітом встановити 1, як рекомендовано в RFC 4122. " Тож перевірте цей восьмий біт!
deinonychusaur

27
hex(mac)щоб отримати знайомий шістнадцятковий формат mac
screenshot345,

43
Або ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))для великого MAC з кожним байтом, розділеним двокрапкою.
tomlogic

5
getnode () повертає щось інше кожен раз, коли я перезавантажую свій ноутбук Windows 7.
nu everest

80

Чисте рішення пітону для цієї проблеми під Linux, щоб отримати MAC для конкретного локального інтерфейсу, спочатку розміщений як коментар vishnubob та вдосконалений Бен Маккі в цьому рецепті 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()

35

netiface - це гарний модуль, який можна використовувати для отримання 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'}]


Використовується особисто, вимагає певної установки / компіляції в кожній системі, але працює добре.
Aatch

22

Ще одна річ, яку ви повинні зауважити, - це те, що 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.

8
Не те, що значення 8-го дорівнює 1 саме тому, що воно не може бути використане мережевою картою. Достатньо лише перевірити цей біт, щоб виявити, чи адреса підроблена чи ні.
Фредерік Гроссханс

15
Перевірка проводиться лише з: if (mac >> 40)% 2: підвищити OSError, "У системі, схоже, немає дійсного MAC"
Frédéric Grosshans

17

Іноді у нас є більше одного мережевого інтерфейсу.

Простий спосіб дізнатися 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")

2
Не дуже корисно для ОС X або Windows. : |
RandomInsano

1
Ідеально підходить для Піса!
MikeT

8

Використовуючи мою відповідь звідси: https://stackoverflow.com/a/18031868/2362361

Важливо знати, для якого ви хочете отримати 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

Тестування:

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

6

Це можна зробити за допомогою 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]

import socketпотім [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]результати в['ab:cd:ef:01:02:03']
Донн Лі

3

Зауважте, що ви можете створити власну міжплатформенну бібліотеку в python, використовуючи умовний імпорт. напр

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

Це дозволить вам використовувати виклики os.system або бібліотеки, орієнтовані на платформу.


2
це насправді не відповідь - лише коментар
Стефано

1

Крос-платформний 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)

Відмова: Я автор пакету.

Оновлення (14 січня 2019 р.): Пакет тепер підтримує лише Python 2.7+ та 3.4+. Ви все ще можете використовувати більш стару версію пакета, якщо вам потрібно працювати зі старшим Python (2.5, 2.6, 3.2, 3.3).


1

Щоб отримати eth0MAC-адресу інтерфейсу,

import psutil

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

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

0

Я не знаю єдиного способу, але ось щось, що може вам бути корисним:

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

Що я б робив у цьому випадку - це перетворити їх на функцію, і на основі ОС вона запустить належну команду, проаналізує, як потрібно, і поверне лише MAC-адресу, відформатовану як ви хочете. Звичайно, все одно, за винятком того, що ви повинні це зробити лише один раз, і це виглядає чистіше від основного коду.


0

Для Linux дозвольте представити скрипт оболонки, який покаже 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 (тимчасово відновиться до фактичної після перезавантаження).


6
Чи має це щось спільне з питанням?
bot47


-8

Для Linux ви можете отримати MAC-адресу за допомогою ioctl SIOCGIFHWADDR.

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, щоб отримати цю інформацію. Ви можете використовувати ctypes для прямого виклику ioctl.


8
-1 Він хоче рішення пітону, тож ви йдіть і дайте йому той самий розроблений розчин C, який замазаний по всій мережі.
Aatch
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.