Bash'ta UUID nasıl oluşturulur?


185

Java'da rastgele bir UUID oluşturmak mümkündür :

UUID uuid = UUID.randomUUID();

Bash'te nasıl yapılır?

Yanıtlar:


225

E2fsprogs paketinin bir uuidgenparçası olan programa bakın .

Göre bu , libuuidşimdi bir parçası olan util-linux ve e2fsprogs içinde içerme aşamalı olarak. Ancak, yeni Ubuntu sistemlerinde, uuidgenşimdi uuid-runtimepakette.

Bir uuid oluşturmak ve onu bir değişkene kaydetmek için:

uuid=$(uuidgen)

Ubuntu sistemimde, alfa karakterleri küçük harf, OS X sistemimde büyük harf olarak çıkarlar (bunu yorum için David ile işaretlediğiniz için teşekkürler).

Tüm büyük harflere geçmek için (yukarıdaki gibi oluşturduktan sonra):

uuid=${uuid^^}

Tüm küçük harflere geçmek için:

uuid=${uuid,,}

Örneğin, iki UUID'niz varsa ve bunları Bash'de karşılaştırmak istiyorsanız, durumlarını dikkate almazsanız, bunun tolower()gibi bir stil karşılaştırması yapabilirsiniz :

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

7
hey, adil değil! e2fsprog'larım bununla gelmedi! bir tane istiyorum, nereden bulabilirim? (güncelleme: ahhh ... debian uuid-runtimegörünürde bir sebep olmadan pakete yapıştırır ... +1 size)
quixote

uuidgen freeBSD'ye yerleşik olarak geliyor. her zaman e2fsprogs paketinde yoktur.
İyi Kişi

1
@Rob: Orijinal sorunuzu cevaplamak için, sürücü etiketleri içindir .
Dennis Williamson,

2
Mac'te uuidgen'in büyük harflerle yayıldığını, Ubuntu'da (uuidgen util-linux 2.20.1) tüm küçük harflerde olduğunu fark ettim. Neden fark? Ayrıca Ubuntu, aracın nereden geldiğini listeledi ancak Mac'te, sürüm bilgisi veya hangi paketten geldiği hakkında bilgi yok.
David

1
@Did: OS X'deki temel işletim sisteminin bir parçası olduğuna inanıyorum. Birinin neden büyük, diğeri daha düşük olduğu hakkında hiçbir fikrim yok. Her echo -e 'f\nF' | grep '[[:xdigit:]]'ikisi de geçerli onaltılık karakterleri temsil ettiği için ( her iki satırı da çıktılar) gerçekten önemli değil . Sizin için önemliyse ve Bash 4'ünüz varsa, bunu küçük harf yapmak için yapabilirsiniz: uuid=$(uuidgen); uuid=${uuid,,}veya bunu büyük harf yapmak için yapabilirsiniz: uuid=$(uuidgen); uuid=${uuid^^}ya da bu tolower()testler boyunca bir stil testi yapmak için :if [[ ${uuid1,,} == ${uuid2,,} ]]
Dennis Williamson

168

Harici bağımlılıklar eklemeden çeşitlilik eklemek için Linux'ta şunları yapabilirsiniz:

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

Kötü uygulamaları, FreeBSD'de linux uyumluluk katmanı altında (linuxulator?) Yaymak,

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

Referanslar:


19
Bu harika.
Tom O'Connor,

3
Bu son derece olmayan taşınabilir olduğu gibi kaçınılmalıdır (her ne FreeBSD gereçleri / kötü yazılmış uygulamalar için / linux / proc / sys / kernel / rasgele / uuid compat)
İyi Kişi

1
Initrd görüntünün içinde kullanım için mükemmel uyum sağlar
Maximilian

2
Bu en iyi cevap olmalı!
dguerri

6
Bu bir Docker konteyner gibi, asgari kurulum için daha iyi bir cevap.
jacderida

34

Sadece eksiksizlik adına ... dbusDebian paketinde yüklü bir UUID üreteci de var . Daha önce etrafa bakmayı özledim. Muhtemelen e2fsprogs paketi ile aynı algoritmadır, ancak çizgi eklememektedir, bu yüzden sizin için biraz daha temiz olabilir:

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

$ dbus-uuidgen
d17b671f98fced5649a856a54b51c9e6

Grawity bir güvenlik ipucu ekliyor: "DBus UUID'ler RFC 4122 ile ilişkili değil veya bunlarla uyumlu değil . Ayrıca, dbus-uuidgen , Unix zaman damgasını her zaman son 4 bayt olarak kullanıyor. Bu nedenle bazı kullanımlar için uygun olmayabilir." (Teşekkürler, Grawity, bunu sayfada görmeliydim.)


7
DBus UUID'leri RFC 4122 ile ilişkili veya uyumlu değildir. Ayrıca, dbus-uuidgenUnix zaman damgasını her zaman son 4 bayt olarak kullanır. Bu yüzden bazı kullanımlar için uygun olmayabilirler.
Ocak'ta

Fedora-25’de de aynı eserler ...
kmonsoor

20

Diğer yürütülebilir bağlı istemiyoruz veya bunları kullanamaz, burada saf bash versiyonu burada :

# 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

TDeğişken elimine edilebilir ve for Tdöngü değiştirilebilir: case $N in 3 | 5 | 7 | 9) printf '-';; esac(tercih edilen ise ayrı satırlarda ayrılmış).
Dennis Williamson,

1
İçindekilerin yanı sıra ifadeleri casekaldırmak için kullanılan bir sürümü gösteren github bağlantısındaki koda bir yorum ekledim . Kodu çok daha düzenli yapar. Her ikisi de olması gerektiğini ve olması gerektiğini unutmayın . ifforB%15B%16B%255B%256
Dennis Williamson,

çevrimiçi olarak bir URL'ye yerleştirin, böylece insanlar kaynak yapabilir ve deneyebilir source <(curl url)ya da her neyse
MrCholo

19

Uuidgen'in bulunmadığı yerlerde bu yazıyı "one-liner" olarak faydalı buldum. Bu aynı zamanda Perl veya Python için harici modüller kurmak için gerekli olan her şeyi atlar.

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

SnowLeopard, Red Hat Valhalla, Solaris 9 4/04 ve başarıyla test edildi. Bu benzersiz olmayan eğilimli olup olmadığını merak ediyorum, ama son 10 yılda 'bit'ten olmadım. Tabii ki head -1ile head -_other-value_ | tail -1de değiştirilebilir .

Açıklamak

/dev/randomve /dev/urandomçekirdek rasgele üreteçleridir.

od (sekizli boşaltma), her satırda 16 bayt üreten bir altıgen çıkış anahtarına (-x) sahiptir.

head-n [| kuyruk -1] (burada n> 0) önceki çıktının yalnızca bir satırını çıkarır.

awkOutputFieldSeparator’u print deyiminde virgülün olduğu her yerde kısa çizgi olacak şekilde ayarlar. 2-9 alanlarını bağımsız olarak belirterek, kısa çizgileri kontrol ederiz ve 'od' ile her bir çıktı satırını ön ekleyen dizin / ofset sayacını çıkarırız.

Sonuç, 8-4-4-4-12küçük harf karakterlerden oluşan bir kalıptır a-f0-9.

993bb8d7-323d-b5ee-db78-f976a59d8284

1
Parlak! bağımlılığı olmayan sadece tek bir çizgi, BSD / macOS uyumlu ... harika
dinigo

Do DEĞİL "kuyruk -1" kullanın. Yalnızca "od -x / dev / urandom" u çalıştırırsanız, sürekli olarak daha fazla rasgele veri satırı üreterek süresiz olarak devam eder. "kuyruk -1", sonsuza dek "son" satırı bekleyen orada oturabilir. Aksi takdirde, iyi bir çözümdür.
UncaAlby

Unutmayın, kuyruk, baş tarafından gönderilen satır sayısı birden fazla olduğunda, isteğe bağlı bir parametre olarak yalnızca "açıklamada" bulunur. Orada tek bir 16 baytlık satırın awk almasını sağlamak ve orjinal komutun bir parçası olmaması. Od'dan başa giden boru, boru çıkışını -1 kuyruğuna sterilize eder. Tecrübelerime göre, zaman kuyruklarının sonsuza kadar beklediği tek şey bir -f tartışması. Açıklamanın, kuyruk -1 kullanımının sadece kafa çıktısı birden fazla satır ürettiğinde gerekli olduğunu belirttiği yerde net olmadığı konusunda özür dilerim.
dan

2
Do not kullanmak, tamamen UUID şartname ihlal eder. Sadece sürüm 4 UUID'nin böyle rastgele olmasına izin verilir.
JLH

3
@jlh Bu sorunun neden kilitlendiğinden emin değilim, ancak işte bu yaklaşımı UUID-v4 ile uyumlu kılan sabit bir sürüm: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

Sadece python kaldığını hissetmediği için:

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

Kabukta kullanmak için:

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

Üretilebilecek UUIDS türleri için Python Belgeleri UUID'sine bakın .

Sistem dışı bir makinede sistemd makine kimliği uyumlu bir dosya oluşturmak için, bu şekilde yapmak için python kullanabilirsiniz:

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

dahili bir kullanıcı birimi nedir?
Alexander Mills

Python hiç çalıştı mı? Bu "Dosya" <string> ", satır 1 alma uuid; yazdır uuid.uuid1 () ^ SözdizimiError: geçersiz sözdizimi `
Alexander Mills

1
python3 -c "import uuid; print(uuid.uuid4())"Python3 için kullanın
abdusco,

11

Perl, e2fsprogspakete dayalı bir UUID kütüphanesi sağlar . Debian sistemimde libuuid-perlpaket var. İşte bir örnek bir astar; man uuiddaha fazlası için bakınız :

$ 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

Bu backticks veya $()notasyon ile bir shellscript eklemek önemsiz olurdu :

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

+1 - Bana çok yardım et!
rafa.ferreira


1

Python kullanarak küçük bir Bash işlevi toplu olarak rastgele sayıda UUID oluşturmak için yazdım:

# 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"')]))'
}

Küçük harfleri tercih ediyorsanız değiştirin:

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

Kime:

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

1

Lütfen OSSP UUID kütüphanesine bakın ( http://www.ossp.org/pkg/lib/uuid/ ) ve kurmayı düşünün. Bazı projeler bunu bir seçenek olarak sunar (örn. PostgreSQL). Yüklü (ör. E2fsprogs) kütüphanemin taşıma kapasitesinin ötesinde olan, sürüm 3 ve sürüm 5 UUID'leri düzgün biçimde işler . Neyse ki, openSUSE ana depolardan birinde bulunuyor. Çalışmak için bir sürüm edinmek Windows (örneğin, Cygwin) veya MySQL'in bir suçu oldu. Gerçekten v3 ve v5 UUID'lere ihtiyaç duyduğum için Linux / PostgreSQL / Python'a (ve SQLyog GUI'yi MySQL / MariaDB'ye çok sevdim) geçiş zamanı geldi gibi görünüyor.


Tamamen katılıyorum! Kullanım durumum için, -v3 ns:URL custom-datatohumlama mekanizması yoluyla ad alanını desteklediği için mükemmeldi .
Roberto Andrade,

1

Bazılarının buraya ulaşacağından eminim ve komut dosyalarında kullanılmak üzere benzersiz bir kimlik oluşturmanın kolay bir yolunu arıyorlar ve bunun gerçek bir UUID olması gerekmiyor.

Öyleyse, yalnızca ikinciye özgü bir kimlik oluşturacak olan aşağıdakileri yapabilirsiniz - yani bunu bir saniye içinde birkaç kez çalıştırırsanız, aynı sonucu elde edersiniz.

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

geçerli sistem saatine göre aşağıdaki gibi kimlikler üretecektir:

U1454423662

NOT: Linux kullanıyorsanız veya bir mac'ta Coreutils kurulu ise, nanosaniye için benzersiz bir kimlik oluşturmak için aşağıdakileri kullanabilirsiniz:

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

ya da hemen hemen her yerde çalışması gereken nanosaniyeye kadar bir python tabanlı çözümü tercih ediyorsanız:

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

1
Bu genel olarak çok kötü bir uygulamadır. Modern bilgisayarlar birçok şeyi paralel olarak mükemmel bir şekilde yürütme ve seri görevleri hızlıca tamamlama yeteneğine sahiptir, ancak bu kimlik, diğerinin bir saniye içindeki tüm çağrılar için aynı olacaktır. Aynı anda bu betiği çalıştıran bilgisayarlardan bahsetmiyorum bile. Daha iyi ama yine de mükemmel olmayan bir seçenek, olduğu mktemp -ugibi olacaktır MYID="$(mktemp -u)". Yeniden başlatılana kadar etrafta boş geçici dosyalar bırakmayı göze alıyorsanız, şunları bırakın -u:MYID="$(mktemp)"
Chris Harrington

Hey ... sadece ikinci noktaya özgü tek iyi puanlar ... Yukarıdaki bazı notları ekleyeceğim ...
Brad Parks

1

Bu iplik, çeşitli örneklerle benim için çok faydalı oldu. Sık sık çeşitli ortamlardan gelen uuid fonksiyonlara ihtiyacım var. Ve saf bash örneklerini sevsem de, bazen farklı bir dilden bir kütüphane kullanmak daha uygun olur.

Bu nedenle, sadece eksiksizlik için, yakut (1.9.3+), bir dizi kullanışlı karma ve id işlevi içeren yerleşik SecureRandom modülüne sahiptir. Bash Cliff'ten bunu yapabilirsiniz.

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
Biraz daha fazla açıklama cevabınıza yardımcı olacaktır
Dave M

x = od -X -A n /dev/random | head -1 | cut -c3-38 bunu size aşağıdaki eko verir: x 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 2526

Dave M, yıllar sonra bash yaparken geri döndüm, bu benim şu anki bilgimin kenarında. Umarım biraz parçalamak yardımcı olur. şerefe, andyfff
andyfff

-1

Java 10 kullanıyorsanız.

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

Java 10 bash değil.
kasperd 12:18

Bir java programını çalıştırmadan terminalde ne kadar çabuk UUID oluşturabildiğine bir örnek verdim. İnsanlar, dbus-uuidgen ve uuidgen kullanmaya örnek verdi . Jshell kullanmanın nesi yanlış?
Amit

1
@amit nokta bir örnek vermek gerekir olmasıdır jshelledilebilir Bash komut dosyası kullanılan ve, değil interaktif bir komut olarak . Orijinal yazıdaki bu çok açık.
Samveen

Bunu listelemek için bir şey yapman gerekiyorsa, yapabilirsin echo "System.out.println(java.util.UUID.randomUUID().toString())" | /Library/Java/JavaVirtualMachines/openjdk-11.0.1.jdk/Contents/Home/bin/jshell -s | grep -v ">" Ama ondan çok daha uzun sürüyor uuidgen.
mlk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.