从类似unix的系统中获取唯一的id

时间:2008-11-30 15:11:18

标签: linux unix uniqueidentifier

我想从任何类Unix系统(如果可能的话)获得一个唯一的id,每次我的应用程序在同一台机器上运行时它都会持久化。如果有可能,我想从Linux或FreeBSD或Solaris等获得相同的ID ...我不想为每台机器生成一个新的id,但是获得一个已经存在的id,我更喜欢这个id来自操作系统,我不喜欢使用类似MAC地址的东西。

如果没有其他可用选项,我可以将MAC与其他内容结合使用,例如id可以是MAC地址组合的md5哈希值。

我想听听你的建议。

如果有用,我的应用程序是用C / C ++编写的。

所有这一切的目的是阻止用户运行我的应用程序两次或更多次。我只想跑一次。

15 个答案:

答案 0 :(得分:28)

根文件系统的UUID怎么样?您可以通过手动解析文件或使用/etc/fstabgetfsent (3)getfsfile (3)获取根文件系统设备。拥有设备后,您可以通过检查/dev/disk/by-uuid中的链接或blkid命令来获取UUID。

答案 1 :(得分:11)

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

答案 2 :(得分:9)

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

FLEXlm还为其节点锁定许可证使用主机标识符。它使用的最常见的主机标识符是您的一个网络接口的以太网MAC地址,在没有任何分隔符的情况下粉碎在一起。

它也可以使用(在Windows上)C:驱动器的卷序列号(再次在没有任何分隔符的情况下一起打碎),在Solaris上使用hostid命令的输出(IIRC,在Sun计算机上,这个number实际上是唯一的,位于系统板上的小型可移动EEPROM中。

虽然MAC地址非常容易伪造,但它现在几乎是普遍的标识符(几乎所有新计算机都至少有一个以太网端口,并且它们在板上很常见),并且实际上是全球性的唯一的(事实上,以太网协议依赖于这种独特性)。这种方法会遇到的主要问题是:

  • 有些计算机有几个以太网地址;其中一些是在主板上,有些是在单独的可移动卡上。
  • 它们非常容易伪造(一些协议依赖于能够改变它们)。
  • 某些虚拟化环境会在每次启动时生成随机的以太网地址(但它们通常可以强制使用固定值)。

答案 3 :(得分:5)

另一个选择是使用从dmidecode派生的信息,这是linux上的一个命令。此信息从/ dev / mem解码,因此需要root访问权限。

据了解,dmidecode读取的信息存在缺陷,因为一些主板制造商谎称或假冒某些领域。

答案 4 :(得分:3)

我不认为这是可能的。 你可以得到的最接近的是创建一个非常长的随机字符串(比如MS do with GUID)并将其存储在你系统的某个地方。

答案 5 :(得分:3)

没有通用和可靠的方法来获得你想要的东西。

答案 6 :(得分:1)

您必须考虑许多设置可能已创建文件系统映像并克隆到许多计算机,而不是单独设置它们。在其他情况下,机器可以多次重新设置。换句话说,操作系统提供的任何内容都不可信任。

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

答案 7 :(得分:1)

您没有提到唯一标识符的稳定性 - 每次运行代码时,您是否始终希望同一主机生成相同的ID?

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

如果是,那么你需要决定什么构成与主机相关的“相同”。一种方法是你建议的,第一个以太网接口的MAC的MD5总和和“某事”。对于那种情况下的“东西”,我会考虑FQDN,除非你的“同一主机”的概念包括FQDN改变......

答案 8 :(得分:1)

您可以获得根文件系统/的UUID,这是相当可靠的,但它不会区分chroot和可能在同一磁盘上运行的vms。

如果您主要处理专用于运行特定操作系统的内部或静态HDD,那么您应该能够使用根文件系统的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结合使用。

答案 9 :(得分:0)

听起来你在寻找UUID。这是一个普遍的通用唯一ID(实际上,与GUID相同)

在不同的库中有很多C ++实现,或者你可以使用uuidgen命令捕获输出。

答案 10 :(得分:0)

大多数类似unix的计算机都有一个可通过/dev/random访问的随机数生成器。您将需要诸如MAC地址和时间之类的东西来为GUID生成器提供真正的唯一性(这是Windows上的GUID生成器所做的)。最重要的是,从/ dev / random获取一些东西会得到一个相当不错的GUID类型构造。在实践中,UUID库在幕后执行此类操作。

如果每台机器只需要一个号码,那么MAC地址可能就足够了。这些由中央机构管理,并且可以合理地假设没有两个MAC地址将是相同的。但是,如果您尝试使用此功能将软件安装绑定到MAC地址,请注意某些组件具有可编程MAC地址或MAC地址的可编程组件。类Unix操作系统,尤其是开源系统,往往没有硬连线序列号。这种方法也可能导致在VM中运行多个软件实例时出现问题。

一个选项可能是USB dongle,,可以从多个制造商处获得。另一个选项可能是许可证服务器,其中唯一代码提供给服务器。同样,针对此的几种罐装解决方案可从不同来源获得。

答案 11 :(得分:0)

你在Windows上提到过你使用了一些GUID ......你有关于它是如何创建的一些细节吗?

除此之外,您可以尝试使用CPU ID或硬盘ID ...我想这些不能更改(但如果更换有故障的硬盘,您将遇到麻烦)。

答案 12 :(得分:0)

Jason Day和A.Danischewski的答案似乎走在了正确的轨道上,但不符合任何"类Unix系统的标准。由于/sbin/blkid/etc/fstab不存在于OSX上。

唯一100%可移植的方法是为您自己的应用程序将创建的文件选择标准位置,例如/etc/YOURAPP.cfg并在那里存储一个UUID。

远非理想,因为另一个人或应用程序可能会删除该文件或更改它,或者如果用户更改了根文件系统,您可能会丢失当前计算机上的ID,或者它可能会在另一台计算机上生成。更不用说读写权限等问题了。

但最终没有"同一台机器"。任何计算机都不会超过其组件+当前配置。我不认为你可以做得比这更好,便携。

答案 13 :(得分:0)

正如其他人所述,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的很好替代品。但是,在virtualbox下,dmidecode -t processor不会给您任何有用的信息。我对其他虚拟平台一无所知。

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

答案 14 :(得分:-2)

您可以在以下位置使用锁定文件:

  • /var/run/yourapp.pid(如果程序由root运行)
  • $ HOME / .yourapp.pid(如果由用户和本地文件系统运行)
  • $ HOME / .yourapp。$(hostname -f).pid(nfs上的主页)

运行程序时,它应该执行以下操作:

lock = open(filename, O_CREAT | O_EXCL);
dprintf(lock, "%u", getpid());

如果打开失败,请检查进程是否仍在运行,如果没有:删除文件并重试。