首先,请注意,对于英特尔Pentium III之后的任何系统,CPUID绝对不是通常可访问的唯一标识标记。虽然用MAC地址对其进行哈希处理肯定会导致唯一的标记,但这仅是由于MAC本身的唯一性质,在这种情况下,CPUID只是偶然的。而且,所产生的哈希值不可能比主板的UUID唯一,并且更容易检索,并且该过程不太容易出错。从wikipedia.org/wiki/cpuid:
EAX = 3:处理器序列号
另请参阅:Pentium III§关于隐私问题的争议
这将返回处理器的序列号。处理器序列号是在Intel Pentium III上引入的,但是出于隐私方面的考虑,此功能不再在以后的型号中实现(始终清除PSN功能位)。Transmeta的Efficeon和Crusoe处理器也提供此功能。但是,AMD CPU在任何CPU型号中均未实现此功能。
您可以自己查看,cat /proc/cpuinfo
甚至可以查看已解析的cpuid lscpu
。
我认为这将为您提供Linux内核识别的网络接口的所有MAC地址:
ip a | sed '\|^ *link[^ ]* |!d;s|||;s| .*||'
如果列表可能包含带有随机生成的MAC的虚拟网卡,则可能有必要对其进行过滤。您可以在ip
直接调用中使用标记来执行此操作。请参阅ip a help
以获取有关如何执行此操作的信息。
另请注意,此问题不是唯一的ip
问题,如果使用也必须解决ifconfig
,但与作为成员的-相比,它可以更可靠地进行处理ip
-它是iproute2
网络套件的一部分,并且正在积极维护- ifconfig
该net-tools
软件包的最后一次发行是在2001年。由于自上次发布以来内核中的功能发生更改,ifconfig
已知会误报某些网络功能标志,因此应尽可能避免使用它。
但是,请理解,使用内核接口名称之类的过滤eth[0-9]
不是这样做的可靠方法,因为udev
在启动过程中,它们可能会根据其并行检测的顺序而改变。有关更多信息,请参见可预测的网络名称。
因为dmidecode
没有安装在我的系统上,所以我首先想到对生成的硬盘序列列表进行哈希处理,例如:
lsblk -nro SERIAL
做lsblk --help
一些细化该列表的线索-例如按磁盘类型。也考虑lspci
和/或lsusb
也许。
合并它们很容易:
{ ip a | sed ... ; lsblk ... ; } | #abbreviated... for brevity...
tr -dc '[:alnum:]' | #deletes all chars not alphanumeric - including newlines
sha256sum #gets your hash
如您所知,您正在将用户的资源最终锁定为他们的唯一ID,并且不能依赖于硬盘的存在,所以我想改变一下策略。
考虑到这一点,我再次查看了文件系统并找到了该/sys/class/dmi/id
文件夹。我检查了一些文件:
cat ./board_serial ./product_serial
###OUTPUT###
To be filled by O.E.M.
To be filled by O.E.M.
但是,这似乎很好,但是我不会发布输出:
sudo cat /sys/class/dmi/id/product_uuid
我希望dmidecode
无论如何都可以从中获取很多信息,实际上看起来确实如此。根据man dmidecode
您的说明,您还可以通过指定参数来简化该工具的使用:
dmidecode -s system-uuid
不过,更简单的是,您可以读取文件。请注意,此特定文件专门标识主板。以下是2007内核补丁的摘录,该补丁最初实现了将这些导出到/sysfs
虚拟文件系统的操作:
+DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_date, 0444, DMI_BIOS_DATE);
+DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor, 0444, DMI_SYS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(board_serial, 0400, DMI_BOARD_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag, 0444, DMI_BOARD_ASSET_TAG);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor, 0444, DMI_CHASSIS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_type, 0444, DMI_CHASSIS_TYPE);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_version, 0444, DMI_CHASSIS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial, 0400, DMI_CHASSIS_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag, 0444, DMI_CHASSIS_ASSET_TAG);
如果主板足够,您也许可以单独使用这些数据来识别系统。但是,您可以按照我对硬盘可能会做的相同方式,将此信息与系统的MAC结合起来:
sudo sh <<\CMD | tr -dc '[:alnum:]' | sha256sum
ip a | sed '\|^ *link[^ ]* |!d;s|||;s| .*||'
cat /sys/class/dmi/id/product_uuid
CMD
Linux内核还可以为您生成UUID:
cat /proc/sys/kernel/random/uuid #new random uuid each time file is read
要么:
cat /proc/sys/kernel/random/boot_id #randomly generated per boot
当然,它是随机生成的,你将不得不重新考虑ID分配,但它是一样容易,因为它得到获得至少。如果您能找到对其进行加密的方法,它应该非常可靠。
最后,在UEFI系统上,这变得容易得多-因为每个EFI固件环境变量都包含其自己的UUID。环境变量{Platform,}LangCodes-${UUID}
应该出现在每个UEFI系统上,应该持续重新启动,甚至包括大多数固件升级和修改,并且任何装有efivarfs
模块的Linux系统都可以列出一个或两个名称,就像:
printf '%s\n' /sys/firmware/efi/efivars/*LangCodes-*
LangCodes-${UUID}
显然已经弃用了较旧的格式- 在较新的系统上应保留该格式,PlatformLangCodes-${UUID}
但根据规范,每个UEFI系统中应存在一个或另一个。您可以毫不费力地定义自己的重新引导持久性变量,并以这种方式更多地使用内核的UUID生成器。如果有兴趣,请查看efitools。