
Возможно ли сгенерировать уникальный идентификатор, который не будет меняться со временем, если только не произойдет изменение оборудования? Оборудование должно быть сгенерировано программой ac.
Это также было бы здорово, если бы это было устойчиво к подмене, как MAC-адрес или подмене серийного номера жесткого диска. Но это не абсолютное требование.
Мне нужен такой идентификатор, чтобы собирать программные данные для статистики с множества разных компьютеров.
Я уже прочитал много подобных постов, например этот: генерировать последовательный уникальный идентификатор машины; но они не соответствуют моим потребностям.
Мне нужно, чтобы эта программа работала от имени обычного пользователя, поэтому я не могу использовать команду типа "dmidecode" и т. п. Даже если у меня нет других решений, кроме как использовать MAC-адреса, я не хочу, чтобы UUID менялся, если пользователь переключается с Wi-Fi на Ethernet, поэтому просто взять первый MAC-адрес может быть проблематично. Вдобавок ко всему, UUID должен оставаться идентичным, даже если они установят VMware или VPN. Так что брать все MAC-адреса — это тоже не вариант, потому что эти предыдущие инструменты генерируют больше сетевых интерфейсов и, следовательно, больше MAC-адресов, тем самым меняя UUID.
Я также хочу, чтобы это работало на виртуальной машине, сгенерированный гостевой UUID должен отличаться от хостового.
Я даже не знаю, есть ли такое решение для этой проблемы. Но я подумал, что нужно взять только mac-адреса всех существующих физических аппаратных интерфейсов, прочитав sys/class/net/*/addresses. Затем добавить все mac-адреса и хэшировать их с помощью sha1 для генерации UUID. Но как мне отфильтровать репертуары, чтобы выбрать только один изменяющийся? И могу ли я быть уверен, что их порядок не будет изменен, тем самым изменив добавленную строку и, следовательно, UUID.
В противном случае, могу ли я получить серийный номер жесткого диска без привилегий root и сторонних инструментов? (Если я смогу найти источник стороннего программного обеспечения, это нормально)
Любые другие решения также будут приветствоваться.
PS: Он должен быть совместим с любыми версиями Linux с ядром 2.6 или выше.
решение1
Короткий ответ
На основании всех моих исследований и попыток я бы сказал, что невозможно создать программу, которая генерировала бы уникальный идентификатор, соблюдая следующие ограничения.
- Идентификатор должен быть одинаковым каждый раз, если он генерируется на одном и том же компьютере.
- Идентификатор должен быть разным, если он сгенерирован на разных компьютерах.
- Программа должна запускаться от имени пользователя.
- Программа должна быть совместима с любым дистрибутивом Linux с версией ядра 2.6 или выше.
- Идентификатор может быть другим, если компьютер был модифицирован (например, при замене оборудования).
- Программа не должна полагаться на сторонние инструменты, которые необходимо устанавливать на компьютере.
Длинный ответ
Здесь я представлю свою попытку с MAC-адресами.
Целью здесь было найти способ извлечь адреса всех физических сетевых интерфейсов. Как обычный пользователь, я увидел, что самый простой способ найти mac-адреса — прочитать системные файлы в каталоге "/sys". Эти файлы доступны с linux 2.6, так что это идеально.
Мои исследования привели меня к следующим наборам правил: https://www.kernel.org/doc/Documentation/sysfs-rules.txt
Использование библиотеки udev, как рекомендовано в этих правилах, невозможно, поскольку ее нужно добавлять извне. Поэтому я обратился к исходникам, которые можно найти здесь:http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev
Из этого я извлек, что для получения MAC-адресов нужно искать "sys/subsystem", если он есть, то искать в нем каталог "net", и вы найдете каталоги с каждым сетевым интерфейсом. Если папки "subsystem" нет, нужно искать каталог "net" в папках "sys/class", "sys/bus" и "sys/block". На самом деле, я всегда находил их в "class", но правила говорят, что этого не следует ожидать.
Выше я сказал, что в папке "net" вы найдете сетевые каталоги, это не совсем так. В Linux 2.6 (я использовал RHEL 4) это каталоги, и внутри вы найдете, среди прочего, файл "address", содержащий mac-адрес, символическую ссылку, указывающую на каталог в "sys/devices". Если в более поздней версии Linux, это будет непосредственно символическая ссылка на каталог в "/sys/devices", в котором вы найдете файл "address". (Я пробовал в RHEL 6, Debian 7, Debian 8, Ubuntu 15 и Ubuntu 15 с ядром, обновленным до Linux 4.3)
Я никогда не видел каталога "/sys/subsystem" даже в новой версии Linux (4.3).
Новая компоновка sysfs( >= linux 3) : Чтобы отличить физический интерфейс от виртуального, я хотел посмотреть на devpath устройства. Символическая ссылка, которая у меня есть в "/sys/class/net", указывает на эти каталоги:
- "/sys/devices/pci0000:00/0000:00:11.0/0000:02:01.0/net/eth0"
- "/sys/devices/virtual/net/eth1"
Eth1 — это фиктивная виртуальная сетевая карта, которую я создал в соответствии с этой темой:Как создать виртуальный интерфейс Ethernet на машине без физического адаптера?
Итак, вы видите, что виртуальные файлы находятся в «виртуальной» папке, и это способ их отличить.
Старая компоновка sysfs(линукс 2.6) :
Виртуальный сетевой интерфейс не имеет символической ссылки «устройство» в своих каталогах.
Вы найдете «/sys/class/net/eth0/device -> /sys/devices....» Но если бы был виртуальный eth1, то такой символической ссылки в «/sys/class/net/eth1» не было бы.
Итак, в целом, используя «opendir», «readdir», «access('...',F_OK)», «fopen».. вы можете получить MAC-адреса только физических интерфейсов.
Затем просто отсортируйте их, чтобы убедиться, что они идут в одном и том же порядке, затем добавьте все в буфер и используйте SHA1 из openssl, выполните небольшой анализ, чтобы сделать его похожим на UUID, и все готово.
Но дело в том, что я не хотел полагаться на тот факт, что где-то в devpath к сетевому устройству будет "виртуальная" папка. В правилах, ссылка на которые приведена выше, никогда не говорилось, что это всегда будет так. Так что проблема не может быть решена таким образом.
Надеюсь, что все мои исследования кому-то помогут.