固定机器的标识符(uuid.getnode)

Key*_*Usr 10 python hardware uuid mac-address identifier

我试图找到一些我可以用作我的脚本的唯一字符串/数字的东西,它固定在一台机器上并且很容易获得(跨平台).我认为一台机器会有一张网卡.我不需要它真正独特,但必要的是它应该长期固定,尽可能少.

我知道MAC可以更改,我可能会在我的脚本中发出警告,但我不希望每天早上都有人更改MAC.

我想出的是uuid.getnode(),但在文档中有:

如果所有获取硬件地址的尝试都失败,我们选择一个随机的48位数字

这是否意味着对于每个函数调用我得到另一个随机数,因此如果MAC无法获得则不可能使用它?

...在具有多个网络接口的计算机上,可以返回其中任何一个的MAC地址.

这句话是否意味着getnode()获得所有可用的随机(或第一)MAC?如果首次获得MAC A而下次获得MAC B怎么办?如果我得到一个固定的列表就没有问题(排序,连接,tadaaa!)

我问,因为我自己无法测试它.

eze*_*ekg 6

我不建议使用 MAC 地址作为唯一的机器标识符,因为它可能会根据所使用的网络而变化。相反,我建议使用机器的本机 GUID,由操作系统在安装过程中分配。我编写了一个小型的跨平台 PyPI 包,用于查询计算机的本机 GUID,称为py-machineid

本质上,它看起来像这样,但通过一些特定于 Windows 的 WMI 注册表查询来获得更准确的 ID。该软件包还支持对 ID 进行哈希处理,以使其匿名。

import subprocess
import sys

def run(cmd):
  try:
    return subprocess.run(cmd, shell=True, capture_output=True, check=True, encoding="utf-8") \
                     .stdout \
                     .strip()
  except:
    return None

def guid():
  if sys.platform == 'darwin':
    return run(
      "ioreg -d2 -c IOPlatformExpertDevice | awk -F\\\" '/IOPlatformUUID/{print $(NF-1)}'",
    )

  if sys.platform == 'win32' or sys.platform == 'cygwin' or sys.platform == 'msys':
    return run('wmic csproduct get uuid').split('\n')[2] \
                                         .strip()

  if sys.platform.startswith('linux'):
    return run('cat /var/lib/dbus/machine-id') or \
           run('cat /etc/machine-id')

  if sys.platform.startswith('openbsd') or sys.platform.startswith('freebsd'):
    return run('cat /etc/hostid') or \
           run('kenv -q smbios.system.uuid')
Run Code Online (Sandbox Code Playgroud)


Key*_*Usr 5

我设法在我的 android 设备上测试了第一部分,并在每次运行新的 python 时创建了随机数,因此它根本无法用于此目的。

第二个问题本身就被淹死了,因为如果在文档中它提到它可能会返回any one of them,那么它就不是你可以依赖的东西(+我找不到可以测试它的机器)。一个不错的包netifaces来拯救,它做了类似的事情

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

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

然而我宁愿放弃使用 MAC,我得到了一些更稳定的东西。

现在是标识符:

1) 窗户:

执行这个并获得输出可能就足够了:

wmic csproduct get UUID
Run Code Online (Sandbox Code Playgroud)

或者我使用过的并且在注册表 ( HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography) 中可用的:

import _winreg
registry = _winreg.HKEY_LOCAL_MACHINE
address = 'SOFTWARE\\Microsoft\\Cryptography'
keyargs = _winreg.KEY_READ | _winreg.KEY_WOW64_64KEY
key = _winreg.OpenKey(registry, address, 0, keyargs)
value = _winreg.QueryValueEx(key, 'MachineGuid')
_winreg.CloseKey(key)
unique = value[0]
Run Code Online (Sandbox Code Playgroud)

2)Linux:

/sys/class/dmi/id/board_serial
Run Code Online (Sandbox Code Playgroud)

或者

/sys/class/dmi/id/product_uuid
Run Code Online (Sandbox Code Playgroud)

或者如果不是root:

cat /var/lib/dbus/machine-id
Run Code Online (Sandbox Code Playgroud)

3)安卓:

如果你正在使用 python 并且不想弄乱 Java 的东西,那么这应该工作得很好:

import subprocess
cmd = ['getprop', 'ril.serialnumber']
self.unique = subprocess.check_output(cmd)[:-1]
Run Code Online (Sandbox Code Playgroud)

但是,如果您喜欢 Java,那么请选择这个答案,尽管 evenANDROID_ID的唯一性在允许更改的情况下相当值得商榷,因此序列号很可能是一个更安全的选择。

请注意,就像链接答案中已经提到的那样,甚至ril.serialnumber可以为空/空或不存在(缺少键)。即使使用官方的Android API也会发生同样的事情,其中明确说明了这一点:

硬件序列号(如果有)。

Mac/iPhone: 我找不到任何解决方案,因为我无法访问其中任何一个,但是如果有一个保存机器 ID 值的变量,那么您应该能够通过简单的方式到达那里subprocess.check_output()