views:

2254

answers:

16

Hello.

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.

It is not a copy protection issue. It is an application for researching purpose.

I know that this may be very difficult to implement but if it was easy, I wouldn't ask for your time.

A: 

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.

Yoni Roit
+1 to cancel down vote. This was better than Blue could have expected at the beginning.
dmckee
GUIDs aren't random, per se. How MS generates them, though, they won't say. They are supposedly non-repeating on the machine that they are generated on.
joseph.ferris
+2  A: 

Both Solaris and Linux provide the hostid(1) utility

Martin v. Löwis
On Linux glibc, gethostid() (which is what hostid uses) returns a value based on the IP address, which is neither unique nor unchanging.
CesarB
That quite depends on the application.
Martin v. Löwis
+1  A: 

I forgot to mention that I don't want to store anything on the system.

Blue
+1  A: 

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.

ironfroggy
That depends on what type of cpu you've got.A while back, Intel started implementing a serial number on Pentium processors that you could get with the cpuid instruction, but they got a lot of blowback from privacy groups about it. I'm not sure they still do it. What if the computer has 2 procs?
Die in Sente
+1  A: 

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.

csexton
Err, no, a UUID is different every time it's generated: "unique id that will be persistent every time my application runs in the same machine"
+1  A: 

hostid is not "unique enough", if I can say that. I want something like GUID that Windows use.

Blue
Can new users edit their own questions? I thought so - and if so, that is the best way to handle extra information.
Jonathan Leffler
+1  A: 

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...

genehack
+1  A: 

Yes, I am looking something like UUID, but as I said, I don't want to generate it because I don't want to store anything on the system. I want to get something that already exists.

Blue
I think that you do not know what you want.
Svante
+1 Harleqin.IMO the primary question is still does it need to be stable or is it a one-time per run sort of thing?
genehack
I answered it in my post below. I want it to be stable.
Blue
You want to get something that already exists reliably from systems where no such thing exists reliably. That leads to immovable objects meeting irresistable forces - it gets messy.
Jonathan Leffler
I know that it is a messy situation and if there is no such thing, I want to reach to that conclusion in order to go to another solution. So an answer "The thing you are searching does not exist" is absolutely acceptable.
Blue
A: 

genehack, you are absolutely right. I should have mentioned that I want always the same host to produce the same ID each time my code is run. And FQDN is one of my thoughts for this "something" but I would like and some other thoughts and suggestions for that "something". And I would prefer that "something" to make the possibility of the id to be unique, as higher as it can.

Blue
so, again, it's back to the question of what makes hosts different from each other. this is something _you_ need to figure out for your problem.note that the "uniqueness" is more a function of the probability of collisions in the hashing algorithm you use, not so much the inputs.
genehack
based on everything you've said so far, i'd go with the SHA1 of the MAC + the FQDN, unless you're in an environment where FQDNs aren't stable (i.e., dynamic DNS, etc.)
genehack
The environment is not stable.
Blue
What defines a host? If I replace the hard drive, is the the same host? If I replace the CPU, is it the same host? What about upgrading the BIOS or reinstalling the OS? There's no unique ID that's on all systems that can't be affected by replacing equipment.
Ben Combee
A: 

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.

ConcernedOfTunbridgeWells
I need one number per machine, which will be persistent. I know all these about MAC addresses and because they can change, they are my last solution.
Blue
+2  A: 

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).
CesarB
+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.
JimB
+1  A: 

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

hop
+1  A: 

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.

Phillip Whelan
A: 

You mentioned that on Windows you use some GUID... Do you have some details about how it is created?

Apart from that, you could try something like CPU ID, or hard disk ID... I suppose those cannot be changed (but you will run into trouble if a faulty hard disk is replaced).

oliver
A: 

You can use a lockfile in places like:

  • /var/run/yourapp.pid (if program run by root)
  • $HOME/.yourapp.pid (if run by user and local filesystem)
  • $HOME/.yourapp.$(hostname -f).pid (home on nfs)

When your program is run, it shall do something like:

lock = open(filename, O_CREAT | O_EXCL);
dprintf(lock, "%u", getpid());

If the open fails, check if the process is still running and if not: delete the file and try again.

+1  A: 

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.

Jason Day