Отримання 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.