25

我想从任何类 Unix 系统(如果可能的话)获得一个唯一的 id,每次我的应用程序在同一台机器上运行时都会保持不变。如果可能的话,我想从 Linux 或 FreeBSD 或 Solaris 等获取相同的 id...来自操作系统,我不喜欢使用 MAC 地址之类的东西。

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

我想听听你的建议。

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

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

4

15 回答 15

30

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

于 2008-12-05T17:55:13.857 回答
9

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

于 2008-11-30T15:50:01.617 回答
9

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

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

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

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

  • 有些计算机有多个以太网地址;其中一些在主板上,一些在单独的可移动卡上。
  • 它们非常容易伪造(并且某些协议依赖于能够更改它们)。
  • 一些虚拟化环境会在每次启动时生成随机以太网地址(但它们通常有一种强制固定值的方法)。
于 2008-11-30T16:20:31.773 回答
6

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

众所周知,dmidecode 读取的信息存在缺陷,因为一些主板制造商在某些字段中撒谎或伪造。

于 2008-12-03T18:10:22.487 回答
5

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

于 2008-11-30T21:31:24.953 回答
2

我不认为这是可能的。最接近的方法是创建一个非常长的随机字符串(就像 MS 对 GUID 所做的那样)并将其存储在系统的某个位置。

于 2008-11-30T15:18:37.343 回答
2

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

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

于 2008-11-30T15:52:11.317 回答
2

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

如果您主要处理专用于运行特定操作系统的内部或静态 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/\"//"'

如果您需要进一步区分同一操作系统的内核版本,或在同一磁盘上运行的不同操作系统,您可以使用来自根 fs UUID 的数据uname和/或将它们与根 fs UUID 结合使用。

于 2015-04-02T15:16:28.113 回答
1

您没有提到唯一标识符需要有多稳定——您是否总是希望同一主机在每次运行代码时产生相同的 ID?

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

如果是,那么您需要确定就主机而言什么构成“相同”。一种方法是按照您的建议,将第一个以太网接口的 MAC 和“某物”的 MD5 和。对于那种情况下的“某事”,我会考虑 FQDN,除非您的“同一主机”概念包括 FQDN 更改......

于 2008-11-30T15:56:56.300 回答
1

As someone else stated, the dmidecode command is an option.

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

I edited the output to hide the UUID of the system I tested on.

There are other things that you can get from dmidecode. dmidecode -t will tell you the categories.

[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

If you're using actual hardware instead of a virtual machine then dmidecode -t processor would be a good option.

[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

Given that the number of processor manufactures is small, this seems like a good alternate to dmidecode -s system-uuid. However, under virtualbox, dmidecode -t processor won't give you anything useful. I don't know about any other virtual platforms.

I'm willing to bet that dmidecode -s system-uuid will also work inside a docker container too but, I can't verify that.

于 2020-07-01T16:33:23.217 回答
0

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

除此之外,您可以尝试诸如 CPU ID 或硬盘 ID 之类的东西……我想这些是无法更改的(但是如果更换有故障的硬盘,您会遇到麻烦)。

于 2008-12-04T14:56:37.370 回答
0

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

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

于 2008-11-30T15:54:13.200 回答
0

大多数类 unix 机器都有一个可通过/dev/random访问的随机数生成器。您将需要一个 MAC 地址和时间来为 GUID 生成器提供真正的唯一性(这是 Windows 上的 GUID 生成器所做的)。最重要的是,从 /dev/random 获取一些东西会给你一个相当好的 GUID 类型构造。在实践中,UUID 库在幕后做这种事情。

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

一种选择可能是 USB加密狗,可以从多家制造商处获得。另一种选择可能是许可证服务器,其中向服务器提供唯一代码。同样,可以从不同来源获得几种罐装解决方案。

于 2008-11-30T16:05:34.393 回答
0

Jason Day 和 A.Danischewski 的答案似乎在正确的轨道上,但不符合您对任何“类 Unix 系统”的标准,因为OSX/sbin/blkid/etc/fstab也不存在。

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

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

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

于 2016-03-22T22:41:26.140 回答
-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());

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

于 2008-12-05T17:18:10.377 回答