从类Unix系统获取唯一标识符

29
我希望能够从任何类Unix系统(如果这是可能的话)中获取一个唯一的持久化ID,以便每次我的应用程序在同一台机器上运行时都具有相同的ID。 如果可能的话,我希望从Linux、FreeBSD、Solaris等获得相同的ID... 我不想为每台机器生成新的ID,而是要获取已经存在的ID,而且我更喜欢此ID来自操作系统,而不是使用类似MAC地址之类的东西。
如果没有其他可用选项,我可以将MAC与其他内容结合使用,例如ID可以是MAC地址和其他信息的组合的MD5哈希值。
我想听听您的建议。
如果有用的话,我的应用程序是用C/C++编写的。
所有这些的目的是防止用户多次运行我的应用程序。我只想运行一次。

我觉得这不太清楚。你想要识别什么?你运行的硬件?用户?还是其他什么?并且要在什么范围内唯一? - dmckee --- ex-moderator kitten
我必须同意。为什么要这么多限制? - Brian C. Lane
我有一个灵感。我认为他想要帮助实现复制限制机制。这使得硬件和uzhin的答案合理。 - dmckee --- ex-moderator kitten
你能澄清一下吗——这是一个关于复制保护的问题吗? - Jeff Atwood
1
在Mac OS X上,您可能会获得系统ID - https://dev59.com/Am_Xa4cB1Zd3GeqP4b7R。 - petert
这个问题已经在这里得到了解决:http://unix.stackexchange.com/questions/144812/generate-consistent-machine-unique-id - nightcod3r
15个回答

30

关于根文件系统的UUID怎么获取呢?你可以从/etc/fstab中获取根文件系统设备,可以手动解析该文件或使用getfsent (3)getfsfile (3)函数。一旦获得设备,你可以通过检查/dev/disk/by-uuid中的链接或使用blkid命令来获取UUID。


http://tools.ietf.org/html/rfc4122 - 该规范定义了UUID(通用唯一标识符)的统一资源名称命名空间,也称为GUID(全局唯一标识符)。 UUID长度为128位,可以保证在空间和时间上的唯一性。 - The Demz
1
UUIDs和Linux:你需要了解的一切 - The Demz
1
有些使用情况下,在软件升级期间整个rootfs都会被替换。这在嵌入式设备上非常普遍,但并不是普遍存在的情况。 - dtoux
此外,一些文件系统没有唯一的标识符(例如FAT衍生物)。 - dtoux

10

通常最好的方法是看看其他人如何解决同样的问题。

FLEXlm 也使用主机标识符来进行其节点锁定许可证。 最常见的主机标识符是您其中一个网络接口的以太网MAC地址,没有任何分隔符。

它还可以使用(在Windows上)C:驱动器的卷序列号(再次没有分隔符);在Solaris上,使用 hostid 命令的输出(如果我没记错,在Sun计算机上,此数字实际上是唯一的,并位于系统板上的小可拆卸EEPROM上)。

虽然MAC地址极易伪造,但它现在几乎成为了一种普遍的标识符(几乎所有新计算机都至少有一个以太网端口,而且很常见它们被集成在主板上),并且实际上旨在全球唯一(事实上,以太网协议依赖于这种唯一性)。您可能会遇到的主要问题:

  • 某些计算机具有多个以太网地址;其中一些位于主板上,一些位于单独的可拆卸卡上。
  • 它们极易伪造(有些协议依赖于能够更改它们)。
  • 一些虚拟化环境在每次启动时生成随机的以太网地址(但它们通常有一种方式来强制使用固定值)。

+1 - 如果有一种可靠的方法来唯一标识Linux系统,Flexlm会使用它,但他们只使用MAC地址。 - JimB

9

Solaris 和 Linux 都提供了 hostid(1) 实用程序。


13
在Linux glibc上,gethostid()函数(也是hostid使用的函数)返回基于IP地址的值,这个值既不是唯一的,也不是不变的。 - CesarB
这相当取决于应用程序。 - Martin v. Löwis
11
我刚在三台不同的电脑上测试了hostid命令(但是它们都使用同一个发行版),所有电脑返回的值都相同。 - picrap
“hostid”不如MAC地址可靠,因为它基于系统的IP地址,而IP地址可能随时更改。在类Unix操作系统中,“hostid”命令用于获取系统的主机标识号。这个唯一的数字是基于机器的IP地址,并以十六进制表示。 - shrewmouse

6
另一种选择是使用在Linux上存在的命令dmidecode所提供的信息。这些信息是从/dev/mem解码而来,因此需要root访问权限。
dmidecode读取的信息已知存在缺陷,因为某些主板制造商会欺骗或伪造一些字段。

1
dmidecode并非所有Linux系统都可用。例如,安装有SLES的IBM POWER系统。 - woverton

5

没有一种通用且可靠的方法可以获得你想要的。


总有办法。可以使用SHA256(/etc/machine-id | /sys/class/net/eth0/address)。我认为这是一个相当好的唯一设备ID,可靠且通用。 - Alex D

2
你可以获取根文件系统 / 的UUID,这是相当可靠的,但它不能区分运行在同一磁盘上的chroots和可能的虚拟机。如果你主要处理专门用于运行特定操作系统的内部或静态硬盘,则应该能够使用根文件系统的UUID来检测系统。
你可以像这样获取根fs的UUID: alias sys_guid='sudo /sbin/blkid | grep "$(df -h / | sed -n 2p | cut -d" " -f1):" | grep -o "UUID=\"[^\"]*\" " | sed "s/UUID=\"//;s/\"//"' 如果你需要进一步区分相同操作系统的内核版本或在同一磁盘上运行的不同操作系统,则可以使用uname的数据和/或将它们与根fs UUID结合使用。

2

我认为这是不可能的。最接近的方法是创建一个非常长的随机字符串(就像微软使用GUID一样),并将其存储在系统中。


+1 取消踩。这比 Blue 开始时预期的要好。 - dmckee --- ex-moderator kitten
GUIDs本质上并不是随机的。然而,微软生成GUID的方法是保密的。据说,在生成GUID的计算机上,它们是不会重复的。 - Joseph Ferris
只是一个快速的更正; GUIDs 可以是随机的,这取决于GUID的类型(特别是版本4 GUID是随机的),并且生成算法在ITU-T Rec. X.667(又名ISO/IEC 9834-8)和RFC 4122中标准化。 - al45tair

2

需要考虑到很多设置可能已经创建了文件系统镜像并克隆到许多机器上,而不是单独设置它们。在其他情况下,一台机器可能会被重新设置多次。换句话说,操作系统提供的任何内容都不能信任。

然而,CPU确实保留了唯一的序列号,但是在不同的系统上访问它应该是不同的。


这取决于您拥有的CPU类型。一段时间以前,英特尔开始在Pentium处理器上实现序列号,您可以使用cpuid指令获取该序列号,但是他们受到了隐私组织的强烈反对。我不确定他们是否仍在这样做。如果计算机有2个处理器会怎么样? - Die in Sente

2

如其他人所说,dmidecode命令是一种选择。

[root@sri-0000-0003 WebGui]# dmidecode -s system-uuid
03001234-1234-1234-1234-000700012345

我编辑了输出,以隐藏我测试系统的UUID。

你可以从dmidecode获取其他信息。 dmidecode -t 将告诉你类别。

[root@sri-0000-0003 WebGui]# dmidecode -t
dmidecode: option requires an argument -- 't'
Type number or keyword expected
Valid type keywords are:
  bios
  system
  baseboard
  chassis
  processor
  memory
  cache
  connect

如果您使用的是实际硬件而不是虚拟机,则dmidecode -t processor是一个不错的选择。
[root@sri-0000-0003 WebGui]# dmidecode -t processor
# dmidecode 3.1
Getting SMBIOS data from sysfs.
SMBIOS 3.0.0 present.

Handle 0x0041, DMI type 4, 48 bytes
Processor Information
        Socket Designation: U3E1
        Type: Central Processor
        Family: Core i3
        Manufacturer: Intel(R) Corporation
        ID: E3 00 00 00 11 22 33 44

鉴于处理器制造商数量很少,这似乎是一个很好的替代方法dmidecode -s system-uuid。然而,在虚拟框中,dmidecode -t processor将不提供有用的信息。我不知道其他虚拟平台的情况。

我愿意打赌dmidecode -s system-uuid在docker容器内也可以工作,但我无法验证。


1

您没有提及唯一标识符需要多稳定 - 您是否希望每次运行代码时始终使用相同的主机生成相同的ID?

如果不是,那么fuzzymonk的uuidgen建议就是您想要的。

如果是,那么您需要决定在主机方面什么构成了“相同”。一种方法是如您所建议的,第一个以太网接口的MAC地址和“某些内容”的MD5校验和。对于“某些内容”,在这种情况下我会考虑FQDN,除非您对“相同主机”的概念包括FQDN更改......


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接