Ottenere un ID univoco da un sistema unix-like

Voglio ottenere da qualsiasi sistema simile a Unix (se questo è ansible) un ID univoco che sarà persistente ogni volta che la mia applicazione viene eseguita nella stessa macchina. Se è ansible, voglio ottenere lo stesso id da Linux o FreeBSD o Solaris, ecc … Non voglio generare un nuovo id per ogni macchina, ma ottenere un id già esistente, e preferisco questo id a provengono dal sistema operativo e non preferisco usare qualcosa come l’indirizzo MAC.

Se non ci sono altre opzioni disponibili, posso usare MAC in combinazione con qualcos’altro, ad esempio l’id può essere l’hash md5 della combinazione dell’indirizzo MAC e qualcos’altro.

Mi piacerebbe ascoltare i tuoi suggerimenti.

Se è utile, la mia applicazione è scritta in C / C ++.

Lo scopo di tutto ciò è di impedire a un utente di eseguire la mia applicazione per due o più volte. Voglio correre solo una volta.

E l’UUID del filesystem di root? È ansible ottenere il dispositivo getfsent (3) da /etc/fstab , analizzando manualmente il file o usando getfsent (3) o getfsfile (3) . Una volta ottenuto il dispositivo, è ansible ottenere l’UUID controllando i collegamenti in /dev/disk/by-uuid o dal comando blkid .

Sia Solaris che Linux forniscono l’utilità hostid (1)

Il modo migliore è, come al solito, vedere come altre persone hanno già risolto lo stesso problema.

FLEXlm utilizza anche un identificativo host per le sue licenze con nodo bloccato. L’identificatore host più comune che utilizza è l’indirizzo MAC ethernet per una delle interfacce di rete, fracassato insieme senza alcun separatore.

Può anche utilizzare (su Windows) il numero di serie del volume dell’unità C: (nuovamente distrutto insieme senza separatori) e su Solaris l’output del comando hostid (IIRC, su computer Sun, questo numero è in realtà univoco e si trova su una piccola EEPROM rimovibile sulla scheda di sistema).

Mentre l’indirizzo MAC è estremamente facile da falsificare, oggigiorno è un identificativo quasi universale (quasi tutti i nuovi computer hanno almeno una porta Ethernet, ed è molto comune per loro essere integrati), e in realtà era destinato a essere globalmente unico (in Infatti, i protocolli Ethernet dipendono da questa unicità). I problemi principali che avresti con questo approccio:

  • Alcuni computer hanno diversi indirizzi Ethernet; alcuni di questi sono presenti sulla scheda principale, alcuni sono su tabs rimovibili separate.
  • Sono estremamente facili da falsificare (e alcuni protocolli dipendono dalla possibilità di modificarli).
  • Alcuni ambienti virtualizzati generano indirizzi ethernet casuali ad ogni avvio (ma di solito hanno un modo per forzare un valore fisso).

Un’altra opzione è usare le informazioni derivate da dmidecode , un comando presente su linux. Questa informazione viene decodificata da / dev / mem, quindi richiede l’accesso come root.

Si sa che le informazioni dmidecode sono errate, in quanto alcuni produttori di tabs madri mentono o falsificano alcuni campi.

Non esiste un modo generale e affidabile per ottenere quello che vuoi.

Non penso sia ansible. Il più vicino che puoi ottenere è creare una stringa casuale molto lunga (come MS con GUID) e memorizzarla da qualche parte nel tuo sistema.

Bisogna considerare che molte configurazioni potrebbero aver creato un’immagine del filesystem e clonare su molte macchine, piuttosto che impostarle singolarmente. In altri casi, una macchina potrebbe essere reimpostata molte volte. In altre parole, tutto ciò che il sistema operativo fornito non può essere considerato attendibile.

Tuttavia, la CPU mantiene un numero seriale univoco, ma l’accesso ad esso dovrebbe essere diverso su sistemi diversi.

Non parli di quanto sia stabile l’identificatore univoco, vuoi sempre che lo stesso host produca lo stesso ID ogni volta che viene eseguito il codice?

Se no, allora il suggerimento di fuzzymonk di uuidgen è quello che vuoi.

Se sì, allora è necessario decidere cosa costituisca lo “stesso” per quanto riguarda l’ospite interessato. Un modo sarebbe come suggerisci, la sum MD5 del MAC della prima interfaccia ethernet e “qualcosa”. Per “qualcosa” in tal caso considererei il FQDN, a meno che la nozione di “stesso host” includa il nome FQDN che cambia …

È ansible ottenere l’UUID del filesystem di root / , che è abbastanza affidabile, ma non distinguerà tra chroot ed eventualmente vms in esecuzione sullo stesso disco.

Se si tratta principalmente di HDD interni o statici dedicati all’esecuzione di un determinato sistema operativo, si dovrebbe essere in grado di utilizzare l’UUID del filesystem di root per rilevare il sistema.

Puoi ottenere l’UUID di root fs con qualcosa del genere: alias sys_guid='sudo /sbin/blkid | grep "$(df -h / | sed -n 2p | cut -d" " -f1):" | grep -o "UUID=\"[^\"]*\" " | sed "s/UUID=\"//;s/\"//"' alias sys_guid='sudo /sbin/blkid | grep "$(df -h / | sed -n 2p | cut -d" " -f1):" | grep -o "UUID=\"[^\"]*\" " | sed "s/UUID=\"//;s/\"//"'

Se è necessario differenziare ulteriormente tra versioni del kernel dello stesso sistema operativo o sistemi operativi diversi in esecuzione sullo stesso disco, è ansible utilizzare i dati da uname e / o combinarli con l’UUID root fs.

Sembra che tu stia cercando UUID. Questo è un ID universalmente comune comune (in realtà, la stessa cosa di un GUID)

Ci sono molte implementazioni C ++ di questo in libs diffrenti, oppure potresti usare il comando uuidgen e catturare l’output.

La maggior parte delle macchine unix ha un generatore di numeri casuali accessibile attraverso / dev / random . Avrete bisogno di qualcosa come un indirizzo MAC e un tempo per dare una vera unicità al generatore GUID (questo è ciò che fa il generatore GUID su Windows). Inoltre, ottenere qualcosa da / dev / random ti darà un costrutto di tipo GUID ragionevolmente buono. In pratica, le librerie UUID fanno questo genere di cose dietro le quinte.

Se hai solo bisogno di un numero per macchina, sarà probabilmente sufficiente un indirizzo MAC. Questi sono amministrati da un corpo centrale e si può ragionevolmente presumere che non ci saranno due indirizzi MAC uguali. Tuttavia, se si sta tentando di utilizzarlo per colbind un’installazione software a un indirizzo MAC, tenere presente che alcuni componenti dispongono di indirizzi MAC programmabili o componenti programmabili dell’indirizzo MAC. I sistemi operativi Unix-like, in particolare quelli open-source, tendono a non avere numeri seriali cablati. Questo approccio può anche causare problemi con l’esecuzione di più istanze del software in VM.

Un’opzione potrebbe essere un dongle USB , che può essere ottenuto da diversi produttori. Un’altra opzione potrebbe essere un server di licenza, in cui il codice univoco viene fornito al server. Ancora una volta, diverse soluzioni in scatola per questo sono disponibili da diverse fonti.

Hai detto che su Windows usi qualche GUID … Hai qualche dettaglio su come è stato creato?

A parte questo, potresti provare qualcosa come l’ID della CPU o l’ID del disco fisso … Suppongo che non sia ansible cambiarli (ma ti troverai nei guai se viene sostituito un disco rigido difettoso).

Le risposte di Jason Day e A.Danischewski sembrano essere sulla strada giusta, ma non soddisfano i criteri di un “sistema simile a Unix” poiché /sbin/blkid e /etc/fstab non esistono su OSX.

L’unico approccio 100% portatile sarebbe quello di scegliere un percorso standard per un file creato dalla propria applicazione, ad esempio /etc/YOURAPP.cfg e archiviare un UUID lì se non ne esiste già uno.

Lontano dall’ideale, dal momento che un’altra persona o applicazione potrebbe cancellare il file o cambiarlo, o se l’utente ha modificato il file system di root, si potrebbe perdere l’ID dal computer corrente o potrebbe nascere su un’altra macchina. Per non parlare dei problemi con permessi di lettura e scrittura e così via.

Ma alla fine non esiste una cosa come “la stessa macchina”. Qualsiasi computer non è né più né meno dei suoi componenti + configurazione attuale. Non penso che tu possa fare di meglio, portabilmente.

Puoi usare un lockfile in posti come:

  • /var/run/yourapp.pid (se il programma è eseguito da root)
  • $ HOME / .yourapp.pid (se eseguito dall’utente e dal filesystem locale)
  • $ HOME / .yourapp. $ (Hostname -f) .pid (home su nfs)

Quando il tuo programma è in esecuzione, deve fare qualcosa del tipo:

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

Se l’apertura fallisce, controlla se il processo è ancora in esecuzione e in caso contrario: elimina il file e riprova.