¿Cómo crear un UUID en bash?


185

En Java es posible crear un UUID aleatorio :

UUID uuid = UUID.randomUUID();

¿Cómo hacer esto en Bash?

Respuestas:


225

Vea el uuidgenprograma que forma parte del paquete e2fsprogs .

De acuerdo con esto , libuuidahora es parte de util-linux y la inclusión en e2fsprogs se está eliminando gradualmente. Sin embargo, en los nuevos sistemas Ubuntu, uuidgenahora está en el uuid-runtimepaquete.

Para crear un uuid y guardarlo en una variable:

uuid=$(uuidgen)

En mi sistema Ubuntu, los caracteres alfabéticos se muestran en minúsculas y en mi sistema OS X, se muestran en mayúsculas (gracias a David por señalar esto en un comentario).

Para cambiar a mayúsculas (después de generarlo como se indica arriba):

uuid=${uuid^^}

Para cambiar a minúsculas:

uuid=${uuid,,}

Si, por ejemplo, tiene dos UUID y desea compararlos en Bash, ignorando su caso, puede hacer una tolower()comparación de estilo como esta:

if [[ ${uuid1,,} == ${uuid2,,} ]]

77
oye, no es justo! ¡mis e2fsprogs no vinieron con eso! Quiero uno, ¿dónde lo consigo? (actualización: ahhh ... debian lo pega en el uuid-runtimepaquete sin razón aparente ... +1 para usted)
quack quixote

uuidgen viene incorporado en freeBSD. no siempre está en el paquete e2fsprogs.
Buena persona

1
@Rob: para responder a su pregunta original, es para etiquetas de unidades .
Dennis Williamson

2
Noto que uuidgen en Mac emite en mayúsculas mientras está en Ubuntu (uuidgen de util-linux 2.20.1) en minúsculas. ¿Por qué la diferencia? También Ubuntu enumeró de dónde vino la herramienta, pero en Mac, no hay información de versión ni de qué paquete vino.
David

1
@David: Creo que es parte del sistema operativo base en OS X. No tengo idea de por qué uno es mayúscula y el otro es inferior. Realmente no importa, ya que representa caracteres hexadecimales válidos ( echo -e 'f\nF' | grep '[[:xdigit:]]'genera ambas líneas). Si es importante para usted y tiene Bash 4, puede hacer esto para que aparezca en minúscula: uuid=$(uuidgen); uuid=${uuid,,}o esto para que sea en mayúscula: uuid=$(uuidgen); uuid=${uuid^^}o algo así para hacer una tolower()prueba de estilo:if [[ ${uuid1,,} == ${uuid2,,} ]]
Dennis Williamson

168

Para agregar variedad sin agregar dependencias externas, en Linux puede hacer:

UUID=$(cat /proc/sys/kernel/random/uuid)

Para propagar malas prácticas, en FreeBSD , bajo la capa de compatibilidad de linux (¿linuxulator?),

UUID=$(cat /compat/linux/proc/sys/kernel/random/uuid)

Referencias


19
Esto es asombroso
Tom O'Connor

3
Esto debe evitarse ya que es altamente no portátil (aunque FreeBSD proporciona / compat / linux / proc / sys / kernel / random / uuid para aplicaciones mal escritas)
Good Person

1
Encaja perfectamente para su uso dentro de la imagen initrd
Maximilian

2
¡Esta debería ser la mejor respuesta!
dguerri

66
Esta es una mejor respuesta para configuraciones realmente mínimas, como un contenedor Docker.
jacderida

34

Solo por razones de integridad ... También hay un generador UUID instalado con el dbuspaquete en Debian. Me perdí mirando alrededor antes. Probablemente sea el mismo algoritmo que el paquete e2fsprogs, pero no agrega guiones, por lo que podría ser un poco más limpio para usted:

$ uuidgen
387ee6b9-520d-4c51-a9e4-6eb2ef15887d

$ dbus-uuidgen
d17b671f98fced5649a856a54b51c9e6

Grawity agrega un consejo de seguridad: "Los UUID de DBus no están relacionados ni son compatibles con RFC 4122. Además, dbus-uuidgen siempre usa la marca de tiempo Unix como los últimos 4 bytes. Por lo tanto, podrían no ser adecuados para algunos usos". (Gracias, Grawity, debería haberlo visto en la página del manual).


77
Los UUID de DBus no están relacionados ni son compatibles con RFC 4122. Además, dbus-uuidgensiempre utiliza la marca de tiempo de Unix como los últimos 4 bytes. Por lo tanto, pueden no ser adecuados para algunos usos.
Grawity

lo mismo funciona en Fedora-25, también ...
kmonsoor

20

Si no desea depender de otros ejecutables, o no puede usarlos, aquí está la versión pura de bash desde aquí :

# Generate a pseudo UUID
uuid()
{
    local N B T

    for (( N=0; N < 16; ++N ))
    do
        B=$(( $RANDOM%255 ))

        if (( N == 6 ))
        then
            printf '4%x' $(( B%15 ))
        elif (( N == 8 ))
        then
            local C='89ab'
            printf '%c%x' ${C:$(( $RANDOM%${#C} )):1} $(( B%15 ))
        else
            printf '%02x' $B
        fi

        for T in 3 5 7 9
        do
            if (( T == N ))
            then
                printf '-'
                break
            fi
        done
    done

    echo
}

[ "$0" == "$BASH_SOURCE" ] && uuid

La Tvariable se puede eliminar y el for Tbucle se puede cambiar a: case $N in 3 | 5 | 7 | 9) printf '-';; esac(dividido en líneas separadas si se prefiere).
Dennis Williamson

1
Agregué un comentario al código en el enlace de github que muestra una versión que usa casepara eliminar las ifdeclaraciones, así como la fordeclaración interna . Hace que el código sea mucho más ordenado. Tenga en cuenta que ambos B%15deberían ser B%16y B%255deberían ser B%256.
Dennis Williamson

ponerlo en línea en una url para que la gente pueda encontrarlo y probarlo source <(curl url)o lo que sea
MrCholo

19

He encontrado este script "one-liner" útil donde uuidgen no está disponible. Esto también evita cualquier necesidad de instalar módulos externos para Perl o Python.

od -x /dev/urandom | head -1 | awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}'

Probado en SnowLeopard, Red Hat Valhalla, Solaris 9 4/04 y más reciente con éxito. Tengo curiosidad por saber si esto es propenso a la no singularidad, pero no he sido 'mordido' en los últimos 10 años. Por supuesto, head -1podría ser reemplazado con head -_other-value_ | tail -1también.

Para explicar,

/dev/randomy /dev/urandomson generadores aleatorios de kernel.

od (volcado octal) tiene un interruptor de salida hexadecimal (-x) que produce 16 bytes por línea.

head-n [| tail -1] (donde n> 0) extrae solo una línea de la salida anterior.

awkconfigura OutputFieldSeparator para que sea un guión en todos los lugares donde aparece una coma en la declaración de impresión. Al especificar los campos 2-9 de forma independiente, controlamos los guiones y eliminamos el índice / contador de desplazamiento con el que 'od' prefija cada línea de salida.

El resultado es un patrón de 8-4-4-4-12caracteres en minúscula a-f0-9.

993bb8d7-323d-b5ee-db78-f976a59d8284

1
¡Brillante! solo una línea sin dependencias, compatible con BSD / macOS ... genial
dinigo

No NO utilizar "cola -1". Si ejecuta solo "od -x / dev / urandom" por sí mismo, continúa indefinidamente, produciendo continuamente más líneas de datos aleatorios. "cola -1" puede quedarse ahí sentado para siempre esperando la "última" línea. De lo contrario, es una buena solución.
UncaAlby

Tenga en cuenta que la cola solo está en la "explicación" como un parámetro opcional cuando el número de líneas de salida por cabeza es mayor que uno. Allí para garantizar la recepción de una sola línea de 16 bytes por awk, y no forma parte del comando original. La tubería a la cabeza desde od ya desinfecta la salida para la tubería a la cola -1. En mi experiencia, el único momento en que la cola espera para siempre es con un argumento -f. Pido disculpas si la explicación no fue clara donde dice que el uso de la cola -1 solo es necesario cuando la salida de la cabeza produce más de una línea.
dan

2
No , no utilizar esto, se viola por completo la especificación UUID. Solo la versión 4 del UUID puede ser aleatoria como esta.
jlh

3
@jlh No estoy seguro de por qué esta pregunta fue bloqueada, pero aquí hay una versión fija que hace que este enfoque sea compatible con UUID-v4:od -x /dev/urandom | head -1 | awk '{OFS="-"; srand($6); sub(/./,"4",$5); sub(/./,substr("89ab",rand()*4,1),$6); print $2$3,$4,$5,$6,$7$8$9}'
Stuart P. Bentley

14

Solo para que Python no se sienta excluido:

python  -c 'import uuid; print uuid.uuid1()'
2d96768e-02b3-11df-bec2-001e68b9d147

Para usarlo en el shell:

myvar=$(python  -c 'import uuid; print uuid.uuid1()')

Consulte el UUID de documentación de Python para conocer los tipos de UUIDS que se pueden generar.

Para generar un archivo systemd machine-id compatible en una máquina que no sea systemd, puede usar python para hacerlo de esta manera:

python -c 'import re; import uuid; print re.sub("-","",str(uuid.uuid4()))' \
 > /etc/machine-id

¿Es uuid un incorporado?
Alexander Mills

¿Python ha funcionado alguna vez? Me sale este `Archivo" <cadena> ", línea 1 import uuid; print uuid.uuid1 () ^ SyntaxError: sintaxis no válida `
Alexander Mills

1
Uso python3 -c "import uuid; print(uuid.uuid4())"para python3
abdusco

11

Perl proporciona una biblioteca UUID basada en el e2fsprogspaquete. En mi sistema Debian es el libuuid-perlpaquete. Aquí hay un ejemplo de una línea; ver man uuidpara más:

$ perl -e 'use UUID;  UUID::generate($uuid);  UUID::unparse($uuid, $string);  print "my new UUID is $string \n";'
my new UUID is 3079e9ce-41d4-4cf3-9f90-d12f8bb752e4

Sería trivial agregar a un shellscript con backticks o $()notación:

#!/bin/bash
# ...do some stuff
$myvar = $(perl -e 'use UUID;  UUID::generate($uuid);  UUID::unparse($uuid, $string);  print "$string";')
# ...do some more stuff

+1 - ¡Ayúdame mucho!
rafa.ferreira


1

Escribí una pequeña función Bash usando Python para generar un número arbitrario de UUID en masa:

# uuid [count]
#
# Generate type 4 (random) UUID, or [count] type 4 UUIDs.
function uuid()
{
    local count=1
    if [[ ! -z "$1" ]]; then
        if [[ "$1" =~ [^0-9] ]]; then
            echo "Usage: $FUNCNAME [count]" >&2
            return 1
        fi

        count="$1"
    fi

    python -c 'import uuid; print("\n".join([str(uuid.uuid4()).upper() for x in range('"$count"')]))'
}

Si prefiere minúsculas, cambie:

python -c 'import uuid; print("\n".join([str(uuid.uuid4()).upper() for x in range('"$count"')]))'

A:

python -c 'import uuid; print("\n".join([str(uuid.uuid4()) for x in range('"$count"')]))'

1

Mire la biblioteca OSSP UUID ( http://www.ossp.org/pkg/lib/uuid/ ) y considere instalarla. Algunos proyectos lo ofrecen como una opción (por ejemplo, PostgreSQL). Maneja correctamente los UUID de la versión 3 y la versión 5 , que estaba más allá de lo que podía manejar mi biblioteca instalada (por ejemplo, e2fsprogs). Afortunadamente, openSUSE lo tiene en uno de los repositorios principales. Conseguir una versión para trabajar con Windows (por ejemplo, Cygwin) o MySQL ha sido un fracaso. Parece que es hora de cambiar a Linux / PostgreSQL / Python (y me encantó la GUI de SQLyog para MySQL / MariaDB) ya que realmente necesito UU3 v3 y v5.


De acuerdo por completo! Para mi caso de uso, fue perfecto, ya que también admite el espacio de nombres a través del -v3 ns:URL custom-datamecanismo de propagación.
Roberto Andrade

1

Estoy seguro de que algunos llegarán aquí, y solo están buscando una manera fácil de generar una ID única para usar en sus scripts, y no necesita ser un verdadero UUID.

Si es así, puede hacer lo siguiente, lo que generará una identificación única hasta el segundo, por lo que si ejecuta esto varias veces en un segundo, aún obtendrá el mismo resultado.

MYID="U$(date +%s)"
echo $MYID

generará identificadores como los siguientes en función de la hora actual del sistema:

U1454423662

NOTA: Si está en Linux o tiene Coreutils instalado en una Mac, puede usar lo siguiente para generar una identificación única para el nanosegundo:

MYID="U$(date +%s%N)"
echo $MYID

o si prefiere una solución basada en Python hasta el nanosegundo, que debería funcionar en casi todas partes, ejecute:

MYUID=U$(python -c'import time; print repr(time.time())')
echo $MYUID

1
En general, esta es una muy mala práctica. Las computadoras modernas son perfectamente capaces de ejecutar muchas cosas en paralelo y completar tareas en serie rápidamente, pero esta identificación será idéntica para cualquier invocación que esté dentro de un segundo de otro. Sin mencionar otras computadoras que ejecutan este script al mismo tiempo. Una opción mejor pero aún no excelente sería mktemp -ucomo en MYID="$(mktemp -u)". Si puede permitirse el lujo de tener archivos temporales vacíos por ahí hasta el reinicio, deje caer -u:MYID="$(mktemp)"
Chris Harrington

Hola ... buenos puntos en el único único para el segundo punto ... Agregaré algunas notas arriba ...
Brad Parks

1

Este hilo, con sus variados ejemplos, fue realmente útil para mí. Con frecuencia necesito funciones uuid de varios entornos diferentes. Y aunque me encantan los ejemplos de bash puro, a veces es más conveniente usar una biblioteca de un idioma diferente.

Entonces, solo por rigor, ruby ​​(1.9.3+) tiene el módulo SecureRandom incorporado que contiene una serie de funciones útiles de hash e id. Desde bash cli, puedes hacer esto.

ruby -r securerandom -e 'puts SecureRandom.uuid'

0
ran=`od -X -A n /dev/random | head -1 | cut -c3-38`

correlation_id=`echo ${ran} | cut -c1-8`-`echo ${ran} | cut -c10-13`-`echo ${ran} | cut -c14-17`-`echo ${ran} | cut -c19-22`-`echo ${ran} | cut -c23-26``echo ${ran} | cut -c28-35`

3
Un poco más de explicación ayudaría a su respuesta
Dave M

x = od -X -A n /dev/random | head -1 | cut -c3-38 le da esto a continuación echo $ x 4151540a 1f7d0bef 8a0725fb d26183a3 uuid = echo ${x} | cut -c1-8- echo ${x} | cut -c10-13- echo ${x} | cut -c14-17- echo ${x} | cut -c19-22- echo ${x} | cut -c23-26``echo ${x} | cut -c28-35 echo $ uuid 4151540a-1f7d-0bef-8a07-25fbd26183a3
andyfff

Dave M, volviendo a hacer bash después de muchos años fuera, esto está muy al borde de mi conocimiento actual. La esperanza de desglosar un poco ayuda. salud, andyfff
andyfff

-1

Si está utilizando Java 10.

$ jshell
jshell> import java.util.*
jshell> String id = UUID.randomUUID().toString();

Java 10 no es bash.
Kasperd

Acabo de dar un ejemplo de lo rápido que puede generar un UUID en la terminal sin ejecutar un programa Java. La gente dio ejemplo del uso de dbus-uuidgen y uuidgen . ¿Qué tiene de malo usar jshell?
amit

1
@amit el punto es que debe dar un ejemplo de dónde jshellse puede usar en scripts de bash , y no como un comando interactivo . Eso está muy claro en la publicación original.
Samveen

Si debe hacer algo, haga una lista de esto, podría hacerlo echo "System.out.println(java.util.UUID.randomUUID().toString())" | /Library/Java/JavaVirtualMachines/openjdk-11.0.1.jdk/Contents/Home/bin/jshell -s | grep -v ">" Pero es mucho más largo que uuidgen.
mlk
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.