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

Fixed identifier for a machine (uuid.getnode)

我正在尝试找到一些我可以用作我的脚本的唯一 string/number 的东西,它固定在机器上并且很容易获得(跨平台)。我假设一台机器会有网卡。我不需要它真的很独特,但必要的是它应该固定在一个很长的 运行 中并且尽可能少见。

我知道 MAC 可以更改,我可能会在我的脚本中对此发出警告,但我不希望任何人每天早上更改 MAC。

我想出来的是uuid.getnode(),但是在docs里面有:

If all attempts to obtain the hardware address fail, we choose a random 48-bit number

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

...on a machine with multiple network interfaces the MAC address of any one of them may be returned.

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

我问是因为我没有办法自己测试。

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

第二个问题本身就被淹没了,因为如果在文档中它提到它可能 return 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'}]

但是我宁愿放弃使用 MAC,我得到了更稳定的东西。

现在是标识符:

1) Windows:

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

wmic csproduct get UUID

或者我使用的那个在注册表中可用 (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]

2) Linux:

/sys/class/dmi/id/board_serial

/sys/class/dmi/id/product_uuid

或者如果不是 root:

cat /var/lib/dbus/machine-id

3) Android:

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

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

但是如果你喜欢Java,那么就选择this answer,尽管即使ANDROID_ID的唯一性如果允许改变也是值得商榷的,因此序列号很可能是一个更安全的赌注。

请注意,就像链接答案中已经提到的那样,即使 ril.serialnumber 也可以是 null/empty 或不存在(缺少密钥)。同样的事情甚至发生在官方 Android API 那里,它清楚地说明了这一点:

A hardware serial number, if available.

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

对于Mac/iphone你可以试试下面的命令:

import subprocess
subprocess.check_output("ioreg -rd1 -c IOPlatformExpertDevice | grep -E '(UUID)'", shell=True).split('"')[-2] # for me i got it on list value -2 if having any trouble try getting it with any alternative list element.

uuid.getnode 将 return 在您的应用程序的单个 运行 中为每次调用提供相同的值。如果它必须服从随机算法,那么当您启动应用程序的新实例时,您将获得不同的值。

getNode 的实施说明了原因。这有点像 python 3.7 中的例程(我的评论,为清楚起见简化了代码)

_node = None

def getnode():

    global _node
    if _node is not None:
        # Return cached value
        return _node

    # calculate node using platform specific logic like unix functions, ifconfig, etc 
    _node = _get_node_from_platform()
    if not _node:
        # couldn't get node id from the system. Just make something up
        _node = _get_random_node() 
    return _node