ura*_*ray 25 linux hardware shell-script hashsum uuid
我们可以为每台 PC 生成一个唯一的 id,比如 uuuidgen,但除非硬件发生变化,否则它永远不会改变?我正在考虑合并 CPUID 和 MACADDR 并将它们散列以生成一致的 ID,但我不知道如何使用 bash 脚本解析它们,我知道如何从中获取 CPUID
dmidecode -t 4 | grep ID
Run Code Online (Sandbox Code Playgroud)
和
ifconfig | grep ether
Run Code Online (Sandbox Code Playgroud)
然后我需要组合这些十六进制字符串并使用 sha1 或 md5 对它们进行散列以创建固定长度的十六进制字符串。
我该如何解析该输出?
ter*_*don 27
这两个怎么样:
$ sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g'
52060201FBFBEBBF
$ ifconfig | grep eth1 | awk '{print $NF}' | sed 's/://g'
0126c9da2c38
Run Code Online (Sandbox Code Playgroud)
然后,您可以将它们组合并散列:
$ echo $(sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g') \
$(ifconfig | grep eth1 | awk '{print $NF}' | sed 's/://g') | sha256sum
59603d5e9957c23e7099c80bf137db19144cbb24efeeadfbd090f89a5f64041f -
Run Code Online (Sandbox Code Playgroud)
要删除尾部破折号,请再添加一根管道:
$ echo $(sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g') \
$(ifconfig | grep eth1 | awk '{print $NF}' | sed 's/://g') | sha256sum |
awk '{print $1}'
59603d5e9957c23e7099c80bf137db19144cbb24efeeadfbd090f89a5f64041f
Run Code Online (Sandbox Code Playgroud)
正如@mikeserv在他的回答中指出的那样,接口名称可以在引导之间更改。这意味着今天的 eth0 明天可能是 eth1,所以如果你 grep foreth0
你可能会在不同的引导下获得不同的 MAC 地址。我的系统不会以这种方式运行,所以我无法真正测试,但可能的解决方案是:
HWaddr
在输出中使用grep forifconfig
但保留所有这些,而不仅仅是与特定 NIC 对应的那个。例如,在我的系统上,我有:
$ ifconfig | grep HWaddr
eth1 Link encap:Ethernet HWaddr 00:24:a9:bd:2c:28
wlan0 Link encap:Ethernet HWaddr c4:16:19:4f:ac:g5
Run Code Online (Sandbox Code Playgroud)
通过获取两个 MAC 地址并将它们传递给sha256sum
,您应该能够获得一个唯一且稳定的名称,而不管哪个 NIC 被称为什么:
$ echo $(sudo dmidecode -t 4 | grep ID | sed 's/.*ID://;s/ //g') \
$(ifconfig | grep -oP 'HWaddr \K.*' | sed 's/://g') | sha256sum |
awk '{print $1}'
662f0036cba13c2ddcf11acebf087ebe1b5e4044603d534dab60d32813adc1a5
Run Code Online (Sandbox Code Playgroud)
请注意,散列与上面的不同,因为我传递了由ifconfig
to返回的两个 MAC 地址sha256sum
。
而是根据硬盘驱动器的 UUID 创建哈希:
$ blkid | grep -oP 'UUID="\K[^"]+' | sha256sum | awk '{print $1}'
162296a587c45fbf807bb7e43bda08f84c56651737243eb4a1a32ae974d6d7f4
Run Code Online (Sandbox Code Playgroud)mik*_*erv 25
首先,请注意,对于Intel Pentium III 之后的任何系统,CPUID 绝对不是通常可访问的唯一标识标记。虽然用 MAC 地址散列它肯定会导致唯一的标记,但这只是由于 MAC 本身的独特品质,在这种情况下 CPUID 只不过是间接的。此外,生成的哈希值不太可能比主板的 UUID 更独特,而且检索起来要容易得多,而且这个过程也不太容易出错。来自wikipedia.org/wiki/cpuid:
EAX=3 : 处理器序列号
这将返回处理器的序列号。处理器序列号是在 Intel Pentium III 上引入的,但出于隐私考虑,此功能不再在以后的型号上实现(PSN 功能位总是被清除)。Transmeta 的 Efficeon 和 Crusoe 处理器也提供此功能。但是,AMD CPU 不会在任何 CPU 型号中实现此功能。
您可以通过执行cat /proc/cpuinfo
或什至仅查看解析的 cpuid 自己lscpu
。
这将为您提供 linux 内核识别的网络接口的所有 MAC 地址,我认为:
ip a | sed '\|^ *link[^ ]* |!d;s|||;s| .*||'
Run Code Online (Sandbox Code Playgroud)
如果该列表可能包含具有随机生成的 MAC 的虚拟网卡,则可能需要过滤该列表。您可以ip
直接在调用中使用标志来做到这一点。有关ip a help
如何执行此操作的信息,请参阅。
另请注意,此问题不是唯一的ip
,如果您使用ifconfig
,也必须加以处理,但是与使用它相比,使用它可以更可靠地处理它ip
- 它是iproute2
网络套件的一部分并得到积极维护 - 而不是它ifconfig
的成员 -该net-tools
软件包的最后一次发布是在 2001 年。由于自上次发布以来内核中的功能发生了变化,ifconfig
已知会误报某些网络功能标志,因此应尽可能避免使用它。
但是请理解,使用内核接口名称进行过滤eth[0-9]
并不是一种可靠的方法,因为它们可以根据udev
引导过程中并行检测的顺序进行更改。有关更多信息,请参阅可预测的网络名称。
因为dmidecode
没有安装在我的系统上,我起初想散列一个生成的硬盘序列列表,如:
lsblk -nro SERIAL
Run Code Online (Sandbox Code Playgroud)
做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
Run Code Online (Sandbox Code Playgroud)
正如您告诉我的那样,您将用户的资源最终锁定到他们的唯一 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.
Run Code Online (Sandbox Code Playgroud)
不过,这个好像还不错,但是我不会发布输出:
sudo cat /sys/class/dmi/id/product_uuid
Run Code Online (Sandbox Code Playgroud)
我希望dmidecode
无论如何都能从那里获取大量信息,事实上它看起来确实如此。根据man dmidecode
您的说法,您还可以通过指定参数来大大简化对该工具的使用:
dmidecode -s system-uuid
Run Code Online (Sandbox Code Playgroud)
不过,更简单的是,您只需读取文件即可。请注意,此特定文件专门标识主板。以下是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);
Run Code Online (Sandbox Code Playgroud)
您可以单独使用该数据来识别系统 - 如果主板足够。但是您可以将这些信息与系统的 MAC 结合起来,就像我演示的处理硬盘的方式一样:
sudo sh <<\CMD | tr -dc '[:alnum:]' | sha256sum
ip a | sed '\|^ *link[^ ]* |!d;s|||;s| .*||'
cat /sys/class/dmi/id/product_uuid
CMD
Run Code Online (Sandbox Code Playgroud)
Linux 内核还可以为您生成 UUID:
cat /proc/sys/kernel/random/uuid #new random uuid each time file is read
Run Code Online (Sandbox Code Playgroud)
或者:
cat /proc/sys/kernel/random/boot_id #randomly generated per boot
Run Code Online (Sandbox Code Playgroud)
诚然,它是随机生成的,您将不得不重新考虑 ID 分配,但它至少很容易获得。如果你能找到一种方法来解决它,它应该是非常可靠的。
最后,在 UEFI 系统上,这变得容易得多——因为每个 EFI 固件环境变量都包含自己的 UUID。环境变量{Platform,}LangCodes-${UUID}
应该存在于每个 UEFI 系统上,应该持续重启,甚至大多数固件升级和修改,并且efivarfs
加载了模块的任何 Linux 系统都可以列出一个或两个名称,如下所示:
printf '%s\n' /sys/firmware/efi/efivars/*LangCodes-*
Run Code Online (Sandbox Code Playgroud)
旧形式 -LangCodes-${UUID}
显然现在已弃用,在较新的系统上应该是,PlatformLangCodes-${UUID}
但根据规范,每个 UEFI 系统中都应该存在一个或另一个。只需很少的努力,您就可以定义自己的重启持久变量,并可能以这种方式更多地使用内核的 UUID 生成器。如果有兴趣,请查看efitools。
XZS*_*XZS 22
许多现代发行版都附带一个文件,/etc/machine-id
其中包含一个很可能是唯一的 16 进制 32 字符字符串。它源自 systemd,其中的联机帮助页包含更多信息,可能适合您的目的。
小智 7
在许多 Linux 机器上,该文件/var/lib/dbus/machine-id
包含每个 Linux 发行版的唯一 ID,可以通过调用dbus_get_local_machine_id()
. 这大概和/etc/machine-id
上面提到的一样。它也适用于虚拟 Linux 安装。我已经在当前的 Ubuntu、SuSE 和 CentOS 发行版上检查过它。
归档时间: |
|
查看次数: |
64723 次 |
最近记录: |