Как сгенерировать uuid linux

Обновлено: 04.07.2024

Can we generate a unique id for each PC, something like uuuidgen, but it will never change unless there are hardware changes? I was thinking about merging CPUID and MACADDR and hash them to generate a consistent ID, but I have no idea how to parse them using bash script, what I know is how can I get CPUID from

then I need to combine those hex strings and hash them using sha1 or md5 to create fixed length hex string.
How can I parse that output?

73.7k 41 41 gold badges 148 148 silver badges 210 210 bronze badges 3,630 11 11 gold badges 33 33 silver badges 41 41 bronze badges What is exactly the problem you are trying to solve using this method? i dont use this to bind a software to a machine, it is linux mining rig that need to identify itself to cloud control and monitoring service, instead of naming thousands of rig manually, i need to uniquely identify them using their hardware ID

6 Answers 6

How about these two:

You can then combine and hash them with:

To remove the trailing dash, add one more pipe:

Grep for HWaddr in the output of ifconfig but keep all of them, not just the one corresponding to a specific NIC. For example, on my system I have:

By grabbing both MAC addresses and passing them through sha256sum , you should be able to get a unique and stable name, irrespective of which NIC is called what:

Note that the hash is different from the ones above because I am passing both MAC addresses returned by ifconfig to sha256sum .

Create a hash based on the UUIDs of your hard drive(s) instead:


205k 55 55 gold badges 390 390 silver badges 588 588 bronze badges @mikeserv ah, yes indeed, I see your point. Thanks, answer edited.

EAX=3: Processor Serial Number

See also: Pentium III § Controversy about privacy issues

This returns the processor's serial number. The processor serial number was introduced on Intel Pentium III, but due to privacy concerns, this feature is no longer implemented on later models (PSN feature bit is always cleared). Transmeta's Efficeon and Crusoe processors also provide this feature. AMD CPUs however, do not implement this feature in any CPU models.

You can view a parsed cpuid yourself by doing cat /proc/cpuinfo or even just lscpu .

This gets you all of the MAC addresses for the network interfaces recognized by the linux kernel, I think:

It may be necessary to filter that list if it might include virtual nics with randomly generated MACs. You can do this with flags in the call to ip directly. See ip a help for information on how to do so.

Also note that this problem is not unique to ip and must also be dealt with if you use ifconfig , but that it can be more reliably handled with ip - which is part of the iproute2 network suite and is actively maintained - than it can with ifconfig - which is a member of the net-tools package and last saw a Linux release in 2001. Due to changing features in the kernel since its last release, ifconfig is known to misreport some networking feature flags and its use should be avoided if at all possible.

Understand, though, that filtering with kernel interface names like eth2 is not a reliable means of doing so, as these can change based on their order of paralleled detection by udev during the boot process. Please see Predictable Network Names for more on that.

Because dmidecode is not installed on my system I at first thought to hash a list of hard disk serials generated like:

Do lsblk --help for some clues on refining that list - by disk type, say. Also consider lspci and/or lsusb maybe.

Combining them is easy:

As you've informed me you're keying user's resources on your end to their unique ids, and hard disks can not be relied upon to exist I thought to change my tack.

That considered, I looked into the filesystem again and found the /sys/class/dmi/id folder. I checked a few of the files:

However, this one seems to be pretty good, but I won't publish the output:

I expect that's where dmidecode gets much of its information anyway and in fact it does look like it. According to man dmidecode you can also simplify your use of that tool a great deal by specifying the argument:

More simple still, though, you can just read the file. Note that this particular file specifically identifies a motherboard. Here's an excerpt from the 2007 kernel patch that originally implemented these exports to the /sysfs virtual filesystem:

You may be able to use that data alone to identify the system - if the motherboard is enough. But you can combine this information with the system's MACs in the same way I demonstrated you might do with hard disks:

The Linux kernel can also generate UUIDs for you:

Granted, it's randomly generated and you will have to rethink ID assignment, but it's about as easy as it gets to get at least. And it should be pretty solid if you can find a means to key it.

Last, on UEFI systems this becomes far easier to do - as every EFI firmware environment variable includes its own UUID. The environment variable LangCodes-$ should be present on every UEFI system, should persist reboots and even most firmware upgrades and modifications, and any Linux system with the efivarfs module loaded can list either or both names as simply as:

The older form - LangCodes-$ is apparently now deprecated, and on newer systems should be PlatformLangCodes-$ but, according to spec, one or the other should be present in every UEFI system. With little effort, you can define your own reboot persistent variables, and maybe make more use of the kernel's UUID generator in that way. If interested, look into efitools.

Sometimes in bash scripting, i need to generate new GUID(Global Unique Identifier) .

I already done that by a simple python script that generates a new guid: see here

But i need to copy this script into any new system that i works on.

My question is: can anybody introduce a command or package that contains similar command ?


6,870 8 8 gold badges 43 43 silver badges 71 71 bronze badges

6 Answers 6

Assuming you don't have uuidgen , you don't need a script:


26.6k 8 8 gold badges 106 106 silver badges 111 111 bronze badges 3,212 1 1 gold badge 24 24 silver badges 38 38 bronze badges

You can use command uuidgen . Simply executing uuidgen will give you time-based UUID:

If you mean uuidgen for Linux, be careful, on Ubuntu 20.04, it is default to generate as random-based UUID. It mentions in man page By default uuidgen will generate a random-based UUID if a high-quality random number generator is present. Otherwise, it will choose a time-based UUID.

Since you wanted a random UUID, you want to use Type 4 instead of Type 1:

This Wikipedia article explains the different types of UUIDs. You want "Type 4 (Random)".

I wrote a little Bash function using Python to generate an arbitrary number of Type 4 UUIDs in bulk:

If you prefer lowercase, change:


22.1k 11 11 gold badges 88 88 silver badges 101 101 bronze badges


6,870 8 8 gold badges 43 43 silver badges 71 71 bronze badges Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

In Python 3, no cast to str is required:

4,633 3 3 gold badges 28 28 silver badges 42 42 bronze badges

If you just want to generate a pseudo-random string with some dashes at locations 8, 12, 16, and 20, you can use apg .

The apg clause generates 32 symbols from [0-9a-f] (lower-case). The series of sed commands add the - tokens and can very likely be shortened.

Note that often an UUID has a particular format:

Here M and N fields encode the version/format of the UUID.

2,773 1 1 gold badge 24 24 silver badges 38 38 bronze badges

Linked

Related

Hot Network Questions

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

I want to get from any Unix-like system (if this is possible) a unique id that will be persistent every time my application runs in the same machine. If it is possible, I want to get the same id from Linux or FreeBSD or Solaris, etc. I don't want to generate a new id for each machine, but get an already existent id, and I prefer this id to come from the operating system and I don't prefer to use something like the MAC address.

If there is no other option available, I can use MAC in combination with something else, for example the id can be the md5 hash of the combination of the MAC address and something else.

I would like to listen to your suggestions.

If it is useful, my application is written in C/C++.

The aim of all this is to prevent a user to run my application for two or more times. I want to run just once.


87.2k 75 75 gold badges 355 355 silver badges 779 779 bronze badges 283 1 1 gold badge 3 3 silver badges 5 5 bronze badges can you clarify -- is this a copy protection question?

15 Answers 15

How about the UUID of the root filesystem? You can get the root filesystem device from /etc/fstab , either by manually parsing the file or by using getfsent (3) or getfsfile (3) . Once you have the device, you can get the UUID by either checking the links in /dev/disk/by-uuid or from the blkid command.

8,669 1 1 gold badge 39 39 silver badges 46 46 bronze badges There are use cases when the entire rootfs is replaced during software upgrade. Quite common on embedded devices, so this is not universal. . also, some filesystems do not have a unique id (FAT derivatives for instance).

Both Solaris and Linux provide the hostid (1) utility

118k 16 16 gold badges 188 188 silver badges 227 227 bronze badges On Linux glibc, gethostid() (which is what hostid uses) returns a value based on the IP address, which is neither unique nor unchanging. I just tested hostid on 3 different computers (but same distro): it returns the same value for all of them.

The best way is, as usual, to see how other people already solved the same problem.

FLEXlm also uses a host identifier for its node-locked licenses. The most common host identifier it uses is the ethernet MAC address for one of your network interfaces, smashed together without any separator.

It can also use (on Windows) the volume serial number of the C: drive (again smashed together without any separators), and on Solaris the output of the hostid command (IIRC, on Sun computers, this number is actually unique, and located on a small removable EEPROM on the system board).

While the MAC address is extremly easy to fake, it is a nearly universal identifer nowadays (almost all new computers have at least one ethernet port, and it is very common for them to be onboard), and actually intended to be globally unique (in fact, the Ethernet protocols depend on this uniqueness). The main problems you would have with this approach:

  • Some computers have several ethernet addresses; some of them are on the main board, some are on separate removable cards.
  • They are extremly easy to fake (and some protocols depend on being able to change them).
  • Some virtualized environment generate random ethernet addresses on each boot (but they usually have a way to force a fixed value).
40.9k 6 6 gold badges 59 59 silver badges 84 84 bronze badges +1 - I was going to mention that if there was a reliable way to uniquely id a linux system, flexlm would use it, but they settle for the mac address.

Another option is to use information derived from dmidecode, a command present on linux. This information is decoded from /dev/mem, therefore requiring root access.

The information dmidecode reads is known to be flawed, as some motherboard manufacturers lie or fake some of the fields.

1,680 2 2 gold badges 17 17 silver badges 27 27 bronze badges dmidecode is not available on all linux systems. For example IBM POWER systems with SLES installed on them.

There is no general and reliable way to get what you want.

I don't think it's possible. The closest you can get is to create a very long random string (like MS do with GUIDs) and store it somewhere on your system.

27k 7 7 gold badges 33 33 silver badges 32 32 bronze badges +1 to cancel down vote. This was better than Blue could have expected at the beginning. Just a quick correction; GUIDs can be random, depending on the type of the GUID (specifically, version 4 GUIDs are random), and the generation algorithm is standardised in ITU-T Rec. X.667 (aka ISO/IEC 9834-8) and RFC 4122.

You have to consider that a lot of setups may have created a filesystem image and cloned to many machines, rather than setting them up individually. In other cases, a machine could get re-setup many times. In other words, anything the OS provided can't be trusted.

However, the CPU does keep a unique serial number, but access to it should be different on different systems.

You can get the UUID of the root filesystem / , that is fairly reliable, yet it won't differentiate between chroots and possibly vms running on the same disk.

If you are mainly dealing with internal or static HDD's that are dedicated to running a particular OS then you should be able to use the UUID of the root filesystem to detect the system.

You can get the UUID of the root fs with something like this: alias sys_guid='sudo /sbin/blkid | grep "$(df -h / | sed -n 2p | cut -d" " -f1):" | grep -o "UUID=\"[^\"]*\" " | sed "s/UUID=\"//;s/\"//"'

If you need to further differentiate between kernel versions of the same OS, or different OS's running on the same disk you can use data from uname and/or combine them with the root fs UUID.

You don't mention how stable the unique identifier needs to be -- do you always want the same host to produce the same ID each time your code is run?

If no, then fuzzymonk's suggestion of uuidgen is what you want.

If yes, then you need to decide what constitutes "same" as far as the host as concerned. One way would be as you suggest, the MD5 sum of the MAC of the first ethernet interface and "something". For "something" in that case I would consider the FQDN, unless your notion of "same host" includes the FQDN changing.

124k 1 1 gold badge 20 20 silver badges 24 24 bronze badges

Sounds like you are looking for UUID. This is a common universally unique id (really, the same thing as a GUID)

There are many C++ implementations of this in diffrent libs, or you could use the uuidgen command and capture the output.

22.3k 15 15 gold badges 53 53 silver badges 54 54 bronze badges

Most unix-like machines have a random number generator accessible through /dev/random. You will need something like a MAC address and a time to give a genuine uniqueness to the GUID generator (this is what the GUID generator on Windows does). On top of this, getting something from /dev/random will get you a reasonably good GUID type construct. In practice, the UUID libraries do this sort of thing behind the scenes.

If you just need one number per machine, than a MAC address will probably be sufficient. These are administered by a central body and one can reasonably assume that no two MAC addresses will be the same. However, if you are trying to use this to tie a software installation to a MAC address be aware that some components have programmable MAC addresses or programmable components of the MAC address. Unix-like Operating systems, particularly open-source ones tend not to have hard-wired serial numbers. This approach may also cause issues with running multiple instances of the software in VM's.

One option might be a USB dongle, which can be obtained from several manufacturers. Another option might be a license server, where the unique code is supplied to the server. Again, several canned solutions for this are available from different sources.

In Java it is possible to create a random UUID:

How to do this in Bash?


5,522 9 9 gold badges 57 57 silver badges 102 102 bronze badges


4,533 10 10 gold badges 31 31 silver badges 29 29 bronze badges Comments disabled on deleted / locked posts / reviews |

14 Answers 14

See the uuidgen program which is part of the e2fsprogs package.

According to this, libuuid is now part of util-linux and the inclusion in e2fsprogs is being phased out. However, on new Ubuntu systems, uuidgen is now in the uuid-runtime package.

To create a uuid and save it in a variable:

On my Ubuntu system, the alpha characters are output as lower case and on my OS X system, they are output as upper case (thanks to David for pointing this out in a comment).

To switch to all upper case (after generating it as above):

To switch to all lower case:

If, for example, you have two UUIDs and you want to compare them in Bash, ignoring their case, you can do a tolower() style comparison like this:


1,825 1 1 gold badge 13 13 silver badges 19 19 bronze badges


58.7k 14 14 gold badges 111 111 silver badges 147 147 bronze badges

To add variety without adding external dependencies, on Linux you can do:

To propagate bad practices, on FreeBSD, under the linux compatibility layer (linuxulator?),


1,825 1 1 gold badge 13 13 silver badges 19 19 bronze badges This should be avoided as it is highly non-portable (although FreeBSD supplies /compat/linux/proc/sys/kernel/random/uuid for poorly written applications) It fits perfectly for usage inside of initrd image This is a better answer for really minimal setups, like a Docker container.

Just for the sake of completeness. There's also a UUID generator installed with the dbus package on Debian. I missed it looking around earlier. It's probably the same algorithm as the e2fsprogs package, but it doesn't add the dashes, so it might be a little cleaner for you:

Grawity adds a safety tip: "DBus UUIDs are not related to or compatible with RFC 4122. Besides, dbus-uuidgen always uses the Unix timestamp as the last 4 bytes. So they might be unsuitable for some uses." (Thanks, Grawity, I should've spotted that in the manpage.)

DBus UUIDs are not related to or compatible with RFC 4122. Besides, dbus-uuidgen always uses the Unix timestamp as the last 4 bytes. So they might be unsuitable for some uses. I added a comment to the code at the github link showing a version using case to eliminate the if statements as well as the inner for statement. It makes the code much neater. Note that both B%15 should be B%16 and B%255 should be B%256 . put it online at a url so people can source it and try it source <(curl url) or whatever

I have found this script "one-liner" useful where uuidgen is not available. This also bypasses any neccessity to install external modules for Perl or Python.

Tested on SnowLeopard, Red Hat Valhalla, Solaris 9 4/04 and newer successfully. I am curious if this is prone to non-uniqueness, but I have not been 'bit'ten in the last 10 years. Of course, head -1 could be replaced with head -_other-value_ | tail -1 too.

/dev/random and /dev/urandom are kernel random generators.

od (octal dump) has a hex output switch (-x) producing 16 bytes per line.

head -n [| tail -1] (where n>0) extracts just one line of the previous output.

awk sets the OutputFieldSeparator to be a hyphen everywhere a comma occurs in the print statement. By specifying fields 2-9 independently, we control the hyphens and strip off the index/offset counter that 'od' prefixes each line of output with.

Читайте также: