linux - Obtener una identificación única de un sistema tipo Unix
uniqueidentifier (14)
Quiero obtener de cualquier sistema tipo Unix (si es posible) una identificación única que será persistente cada vez que mi aplicación se ejecute en la misma máquina. Si es posible, quiero obtener el mismo ID de Linux o FreeBSD o Solaris, etc ... No quiero generar un nuevo ID para cada máquina, pero obtengo una identificación ya existente, y prefiero esta identificación a vienen del sistema operativo y no prefiero usar algo como la dirección MAC.
Si no hay otra opción disponible, puedo usar MAC en combinación con otra cosa, por ejemplo, el ID puede ser el hash md5 de la combinación de la dirección MAC y algo más.
Me gustaría escuchar tus sugerencias.
Si es útil, mi aplicación está escrita en C / C ++.
El objetivo de todo esto es evitar que un usuario ejecute mi aplicación dos o más veces. Quiero correr solo una vez
Debe tener en cuenta que muchas configuraciones pueden haber creado una imagen del sistema de archivos y clonado en muchas máquinas, en lugar de configurarlas individualmente. En otros casos, una máquina podría volver a configurar muchas veces. En otras palabras, cualquier cosa que el sistema operativo proporcione no puede ser confiable.
Sin embargo, la CPU mantiene un número de serie único, pero el acceso a él debe ser diferente en diferentes sistemas.
La mayoría de las máquinas de tipo Unix tienen un generador de números aleatorios accesible a través de /dev/random . Necesitará algo así como una dirección MAC y una hora para dar una originalidad única al generador GUID (esto es lo que hace el generador GUID en Windows). Además de esto, obtener algo de / dev / random te dará un constructo tipo GUID razonablemente bueno. En la práctica, las bibliotecas de UUID hacen este tipo de cosas detrás de escena.
Si solo necesita un número por máquina, entonces una dirección MAC probablemente sea suficiente. Estos son administrados por un organismo central y uno puede suponer razonablemente que no habrá dos direcciones MAC iguales. Sin embargo, si está intentando usar esto para vincular una instalación de software a una dirección MAC, tenga en cuenta que algunos componentes tienen direcciones MAC programables o componentes programables de la dirección MAC. Los sistemas operativos tipo Unix, particularmente los de código abierto, tienden a no tener números de serie cableados. Este enfoque también puede causar problemas con la ejecución de varias instancias del software en las máquinas virtuales.
Una opción podría ser un dongle, USB dongle, que se puede obtener de varios fabricantes. Otra opción podría ser un servidor de licencias, donde el código único se suministra al servidor. Nuevamente, varias soluciones enlatadas para esto están disponibles de diferentes fuentes.
La mejor manera es, como de costumbre, ver cómo otras personas ya resolvieron el mismo problema.
FLEXlm también usa un identificador de host para sus licencias de nodo bloqueado. El identificador de host más común que utiliza es la dirección MAC de Ethernet para una de sus interfaces de red, unidas sin ningún separador.
También puede usar (en Windows) el número de serie del volumen de la unidad C: (otra vez destruido sin separadores), y en Solaris el resultado del comando hostid (IIRC, en computadoras Sun, este número es realmente único, y está ubicado en una pequeña EEPROM extraíble en la placa del sistema).
Si bien la dirección MAC es extremadamente fácil de falsificar, hoy en día es un identificador casi universal (casi todas las computadoras nuevas tienen al menos un puerto Ethernet, y es muy común que estén a bordo), y en realidad la intención es ser único en el mundo (en de hecho, los protocolos de Ethernet dependen de esta singularidad). Los principales problemas que tendría con este enfoque:
- Algunas computadoras tienen varias direcciones de ethernet; algunos de ellos están en el tablero principal, algunos están en tarjetas removibles separadas.
- Son extremadamente fáciles de falsificar (y algunos protocolos dependen de poder cambiarlos).
- Algunos entornos virtualizados generan direcciones de Ethernet al azar en cada arranque (pero generalmente tienen una forma de forzar un valor fijo).
Las respuestas de Jason Day y A.Danischewski parecen estar en el camino correcto, pero no cumplen sus criterios de ningún "sistema tipo Unix" ya que /sbin/blkid
y /etc/fstab
no existen en OSX.
El único enfoque 100% portátil sería elegir una ubicación estándar para un archivo que creará su propia aplicación, por ejemplo, /etc/YOURAPP.cfg
y almacenar un UUID allí si todavía no existe uno.
Lejos de ser ideal, ya que otra persona o aplicación podría eliminar el archivo o cambiarlo, o si el usuario cambió el sistema de archivos raíz, podría perder la ID de la máquina actual o podría surgir en otra máquina. Por no mencionar los problemas con los permisos de lectura y escritura, etc.
Pero al final no existe "la misma máquina". Cualquier computadora no es más ni menos que sus componentes + configuración actual. No creo que puedas hacer nada mejor que esto, de forma portátil.
No creo que sea posible. Lo más cercano que puede obtener es crear una cadena aleatoria muy larga (como MS do con GUIDs) y almacenarla en algún lugar de su sistema.
No hay una manera general y confiable de obtener lo que desea.
No menciona cuán estable debe ser el identificador único: ¿siempre quiere que el mismo host produzca el mismo ID cada vez que se ejecuta su código?
Si no, entonces la sugerencia de fuzzymonk de uuidgen es lo que quieres.
En caso afirmativo, debe decidir qué constituye "lo mismo" en lo que concierne al host. Una manera sería la que sugiera, la suma MD5 del MAC de la primera interfaz ethernet y "algo". Para "algo" en ese caso consideraría el FQDN, a menos que su noción de "mismo host" incluya el cambio de FQDN ...
Otra opción es usar información derivada de dmidecode , un comando presente en Linux. Esta información se decodifica desde / dev / mem, por lo tanto, requiere acceso a la raíz.
Se sabe que la información que dmidecode lee es defectuosa, ya que algunos fabricantes de placas madre mienten o falsifican algunos de los campos.
Parece que estás buscando UUID. Esta es una identificación universal única (en realidad, lo mismo que una GUID)
Hay muchas implementaciones de C ++ de esto en bibliotecas diferentes, o puede usar el comando uuidgen y capturar el resultado.
Puede obtener el UUID del sistema de archivos raíz /
, que es bastante confiable, pero no diferenciará entre chroots y posiblemente vms que se ejecutan en el mismo disco.
Si se trata principalmente de discos duros internos o estáticos que están dedicados a ejecutar un sistema operativo en particular, entonces debería poder usar el UUID del sistema de archivos raíz para detectar el sistema.
Puede obtener el UUID de la raíz fs con algo como esto: 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//"//"''
Si necesita diferenciar aún más entre versiones del kernel del mismo sistema operativo o diferentes sistemas operativos que se ejecutan en el mismo disco, puede usar los datos de uname
y / o combinarlos con el UUID raíz fs.
Puede usar un archivo de bloqueo en lugares como:
- /var/run/yourapp.pid (si el programa se ejecuta por root)
- $ HOME / .yourapp.pid (si lo ejecuta el usuario y el sistema de archivos local)
- $ HOME / .yourapp. $ (Nombre de host -f) .pid (inicio en nfs)
Cuando se ejecuta su programa, debe hacer algo como:
lock = open(filename, O_CREAT | O_EXCL);
dprintf(lock, "%u", getpid());
Si la apertura falla, verifique si el proceso aún se está ejecutando y, de no ser así, elimine el archivo y vuelva a intentarlo.
Tanto Solaris como Linux proporcionan la utilidad hostid
(1)
Usted mencionó que en Windows usa algunos GUID ... ¿Tiene algunos detalles sobre cómo se creó?
Aparte de eso, podrías probar algo como la ID de la CPU o la ID del disco duro ... Supongo que no se pueden cambiar (pero tendrás problemas si se reemplaza un disco duro defectuoso).
¿Qué tal el UUID del sistema de archivos raíz? Puede obtener el dispositivo del sistema de archivos raíz desde /etc/fstab
, ya sea analizando manualmente el archivo o usando getfsent (3)
o getfsfile (3)
. Una vez que tenga el dispositivo, puede obtener el UUID revisando los enlaces en /dev/disk/by-uuid
o desde el comando blkid
.