วิธีสร้าง UUID ใน bash


185

ใน Java เป็นไปได้ที่จะสร้างUUIDแบบสุ่ม:

UUID uuid = UUID.randomUUID();

วิธีการทำเช่นนี้ใน Bash

คำตอบ:


225

ดูuuidgenโปรแกรมที่เป็นส่วนหนึ่งของแพ็คเกจe2fsprogs

ตามนี้ , libuuidตอนนี้เป็นส่วนหนึ่งของutil ลินุกซ์และรวมอยู่ใน e2fsprogs จะถูกแบ่งออก อย่างไรก็ตามในระบบ Ubuntu ใหม่uuidgenตอนนี้อยู่ในuuid-runtimeแพ็คเกจ

ในการสร้าง uuid และบันทึกไว้ในตัวแปร:

uuid=$(uuidgen)

ในระบบ Ubuntu ของฉันตัวอักษรอัลฟาจะถูกส่งออกเป็นตัวพิมพ์เล็กและบนระบบ OS X ของฉันมันจะถูกส่งออกเป็นตัวพิมพ์ใหญ่ (ขอบคุณ David ที่ชี้ให้เห็นสิ่งนี้ในความคิดเห็น)

หากต้องการเปลี่ยนเป็นตัวพิมพ์ใหญ่ทั้งหมด (หลังจากสร้างตามด้านบน):

uuid=${uuid^^}

วิธีเปลี่ยนเป็นตัวพิมพ์เล็กทั้งหมด:

uuid=${uuid,,}

ตัวอย่างเช่นถ้าคุณมี UUID สองตัวและคุณต้องการเปรียบเทียบใน Bash โดยไม่สนใจขนาดตัวพิมพ์คุณสามารถทำการtolower()เปรียบเทียบสไตล์ดังนี้

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

7
เฮ้ไม่ยุติธรรม! e2fsprogs ของฉันไม่ได้มาพร้อมกับสิ่งนั้น! ฉันต้องการหนึ่งฉันจะได้รับมันที่ไหน (อัปเดต: อ่าา ... เดเบียนติดมันในuuid-runtimeแพ็คเกจโดยไม่มีเหตุผลที่ชัดเจน ... +1 ให้คุณ)
ต้มตุ๋น Quixote

uuidgen มาในตัวบน freeBSD ไม่ได้อยู่ในแพ็คเกจ e2fsprogs เสมอไป
คนดี

1
@ Rob: เพื่อที่จะตอบคำถามเดิมของคุณจะเป็นสำหรับป้ายชื่อไดรฟ์
Dennis Williamson

2
ฉันสังเกตเห็น uuidgen บน Mac ปล่อยออกมาเป็นตัวพิมพ์ใหญ่ในขณะที่ Ubuntu (uuidgen จาก util-linux 2.20.1) ในตัวพิมพ์เล็กทั้งหมด ทำไมถึงแตกต่าง Ubuntu ยังระบุว่าเครื่องมือมาจากที่ใด แต่บน Mac ไม่มีข้อมูลรุ่นหรือแพคเกจใดมาจาก
เดวิด

1
@ David: ฉันเชื่อว่ามันเป็นส่วนหนึ่งของระบบปฏิบัติการพื้นฐานใน OS X ฉันไม่ทราบว่าทำไมตัวพิมพ์ใหญ่ถึงเล็กและอีกอันต่ำกว่า มันไม่สำคัญเลยเพราะทั้งสองแสดงถึงอักขระฐานสิบหกที่ถูกต้อง ( echo -e 'f\nF' | grep '[[:xdigit:]]'เอาต์พุตทั้งสองบรรทัด) ถ้ามันเป็นเรื่องสำคัญสำหรับคุณและคุณมี Bash 4 คุณสามารถทำสิ่งนี้เพื่อทำให้ตัวพิมพ์เล็ก: uuid=$(uuidgen); uuid=${uuid,,}หรือเพื่อให้เป็นตัวพิมพ์ใหญ่: uuid=$(uuidgen); uuid=${uuid^^}หรือบางอย่างตามแนวเหล่านี้เพื่อทำtolower()แบบทดสอบ:if [[ ${uuid1,,} == ${uuid2,,} ]]
Dennis Williamson

168

ในการเพิ่มความหลากหลายโดยไม่ต้องเพิ่มการพึ่งพาภายนอกบนLinuxคุณสามารถทำได้:

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

เพื่อเผยแพร่แนวทางปฏิบัติที่ไม่ดีบนFreeBSDภายใต้เลเยอร์ความเข้ากันได้ของ linux (linuxulator?)

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

อ้างอิง:


19
นี่มันเจ๋งมาก.
Tom O'Connor

3
สิ่งนี้ควรหลีกเลี่ยงเนื่องจากไม่สามารถพกพาได้สูง (แม้ว่า FreeBSD supplies / compat / linux / proc / sys / kernel / random / uuid สำหรับแอปพลิเคชันที่เขียนไม่ดี)
บุคคลที่ดี

1
มันเหมาะอย่างยิ่งสำหรับการใช้งานภายในของภาพเริ่มต้น
Maximilian

2
นี่ควรเป็นคำตอบที่ดีที่สุด!
dguerri

6
นี่เป็นคำตอบที่ดีกว่าสำหรับการตั้งค่าเล็กน้อยเช่นคอนเทนเนอร์ Docker
jacderida

34

เพียงเพื่อความสมบูรณ์ ... นอกจากนี้ยังมีตัวสร้าง UUID ที่ติดตั้งพร้อมกับdbusแพ็คเกจบน Debian ฉันคิดถึงมันก่อนหน้านี้ อาจเป็นอัลกอริทึมเดียวกับแพคเกจ e2fsprogs แต่ไม่เพิ่มขีดกลางดังนั้นมันอาจจะสะอาดกว่าสำหรับคุณเล็กน้อย:

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

$ dbus-uuidgen
d17b671f98fced5649a856a54b51c9e6

Grawity เพิ่มเคล็ดลับความปลอดภัย: "DBus UUIDs ไม่เกี่ยวข้องหรือเข้ากันได้กับRFC 4122นอกจากนี้dbus-uuidgenมักใช้ Unix timestamp เป็น 4 ไบต์สุดท้ายดังนั้นจึงอาจไม่เหมาะสมสำหรับการใช้งานบางอย่าง" (ขอบคุณ Grawity ฉันควรจะเห็นสิ่งนั้นใน manpage)


7
DBus UUID ไม่เกี่ยวข้องหรือเข้ากันได้กับ RFC 4122 นอกจากนี้ให้dbus-uuidgenใช้การประทับเวลา Unix เป็น 4 ไบต์สุดท้ายเสมอ ดังนั้นจึงอาจไม่เหมาะสมสำหรับการใช้งานบางอย่าง
grawity

งานเดียวกันกับ Fedora-25 เช่นกัน ...
kmonsoor

20

หากคุณไม่ต้องการพึ่งพาไฟล์ปฏิบัติการอื่นหรือไม่สามารถใช้งานได้นี่คือเวอร์ชั่นทุบตีแท้จากที่นี่ :

# 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

Tตัวแปรสามารถกำจัดและfor Tวงสามารถเปลี่ยนเป็น: case $N in 3 | 5 | 7 | 9) printf '-';; esac(แตกออกในบรรทัดแยกกันถ้าต้องการ)
Dennis Williamson

1
ฉันเพิ่มความคิดเห็นไปยังรหัสที่ลิงค์ github แสดงเวอร์ชันที่ใช้caseในการกำจัดifคำสั่งรวมถึงforคำสั่งด้านใน มันทำให้รหัส neater มาก โปรดทราบว่าทั้งสองB%15ควรจะเป็นB%16และควรจะเป็นB%255 B%256
Dennis Williamson

ใส่ออนไลน์ใน url เพื่อให้ผู้คนสามารถหาแหล่งและลองมัน source <(curl url)หรืออะไรก็ตาม
MrCholo

19

ฉันพบสคริปต์นี้ "หนึ่งซับ" มีประโยชน์ที่ uuidgen ไม่สามารถใช้ได้ สิ่งนี้ยังเลี่ยงความจำเป็นในการติดตั้งโมดูลภายนอกสำหรับ Perl หรือ Python

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 และใหม่กว่าได้สำเร็จ ฉันสงสัยว่าสิ่งนี้มีแนวโน้มที่จะไม่ใช่ลักษณะเฉพาะ แต่ฉันไม่ได้ 'bit'ten ในช่วง 10 ปีที่ผ่านมา แน่นอนhead -1สามารถถูกแทนที่ด้วยhead -_other-value_ | tail -1เช่นกัน

อธิบาย,

/dev/randomและ/dev/urandomเป็นเครื่องกำเนิดไฟฟ้าแบบสุ่มของเคอร์เนล

od (ดัมพ์ฐานแปด) มีสวิตช์เอาต์พุตฐานสิบหก (-x) ที่สร้าง 16 ไบต์ต่อบรรทัด

head-n [| tail -1] (โดยที่ n> 0) แยกเพียงหนึ่งบรรทัดของเอาต์พุตก่อนหน้า

awkตั้ง OutputFieldSeparator ให้เป็นเครื่องหมายยติภังค์ทุกที่ที่มีเครื่องหมายจุลภาคเกิดขึ้นในคำสั่งพิมพ์ ด้วยการระบุฟิลด์ 2-9 อย่างอิสระเราจะควบคุมเครื่องหมายขีดคั่นและตัดการนับดัชนี / ออฟเซ็ตที่นำหน้า 'od' แต่ละบรรทัดของเอาต์พุตด้วย

ผลที่ได้คือรูปแบบของตัวอักษรกรณีที่ต่ำกว่า8-4-4-4-12a-f0-9

993bb8d7-323d-b5ee-db78-f976a59d8284

1
ยอดเยี่ยม! เป็นเพียงบรรทัดเดียวที่ไม่มีการพึ่งพา, รองรับ BSD / macOS ... เยี่ยมมาก
นิโก

อย่าไม่ใช้ "หาง -1" หากคุณเรียกใช้เพียงแค่ "od -x / dev / urandom" ด้วยตัวเองมันจะทำงานต่อไปเรื่อย ๆ เพื่อสร้างข้อมูลสุ่มจำนวนมากอย่างต่อเนื่อง "หาง -1" อาจนั่งอยู่ที่นั่นตลอดไปเพื่อรอสาย "สุดท้าย" มิฉะนั้นมันเป็นทางออกที่ดี
UncaAlby

โปรดทราบหางเป็นเพียง "คำอธิบาย" เป็นพารามิเตอร์ทางเลือกเมื่อจำนวนบรรทัดที่ส่งออกโดยหัวมีค่ามากกว่าหนึ่ง เพื่อให้แน่ใจว่าได้รับบรรทัดเดียวขนาด 16 ไบต์โดย awk และไม่ได้เป็นส่วนหนึ่งของคำสั่งดั้งเดิม ไปป์จากหัว od แล้ว sanitizes เอาท์พุทสำหรับ piping ไปหาง -1 จากประสบการณ์ของฉันหางเวลาเดียวที่รอตลอดไปคืออาร์กิวเมนต์ -f ฉันขอโทษถ้าคำอธิบายไม่ชัดเจนซึ่งระบุว่าการใช้ tail -1 นั้นจำเป็นเฉพาะเมื่อเอาต์พุตของหัวสร้างมากกว่าหนึ่งบรรทัด
แดน

2
อย่าได้ใช้นี้มันสมบูรณ์ละเมิดข้อกำหนด UUID UUID รุ่น 4 เท่านั้นที่ได้รับอนุญาตให้สุ่มแบบนี้
jlh

3
@jlh ฉันไม่แน่ใจว่าทำไมคำถามนี้ถูกล็อค แต่นี่เป็นรุ่นที่แก้ไขที่ทำให้วิธีการนี้เป็นไปตามมาตรฐาน 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

ไพ ธ อนรู้สึกไม่ออก:

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

วิธีใช้ในเชลล์:

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

ดูPython Documentation UUIDสำหรับประเภทของ UUIDS ที่สามารถสร้างได้

ในการสร้างไฟล์ที่เข้ากันได้กับ systemd machine-id บนเครื่องที่ไม่ใช่ systemd คุณสามารถใช้ python เพื่อทำสิ่งนี้:

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

เป็น uuid ในตัวหรือไม่
Alexander Mills

หลามเคยทำงานไหม? ฉันได้รับ `ไฟล์" <string> "บรรทัดที่ 1 นำเข้า uuid; พิมพ์ uuid.uuid1 () ^ SyntaxError: ไวยากรณ์ไม่ถูกต้อง `
Alexander Mills

1
ใช้python3 -c "import uuid; print(uuid.uuid4())"สำหรับ python3
abdusco

11

Perl ให้ห้องสมุด UUID ตามe2fsprogsแพคเกจ ในระบบ Debian ของฉันมันเป็นlibuuid-perlแพ็คเกจ นี่คือตัวอย่างหนึ่งซับ; ดูman uuidเพิ่มเติมที่:

$ 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

นี่จะเป็นเรื่องเล็กน้อยที่จะเพิ่มลงใน shellscript พร้อม backticks หรือ$()notation:

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

+1 - ช่วยฉันได้มาก!
rafa.ferreira


1

ฉันเขียนฟังก์ชัน Bash เล็กน้อยโดยใช้ Python เพื่อสร้างจำนวน UUID จำนวนมากโดยพลการ:

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

หากคุณต้องการตัวพิมพ์เล็กเปลี่ยน:

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

ไปที่:

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

1

โปรดดูที่ห้องสมุด OSSP UUID ( http://www.ossp.org/pkg/lib/uuid/ ) และพิจารณาติดตั้ง บางโครงการเสนอเป็นตัวเลือก (เช่น PostgreSQL) มันจัดการเวอร์ชั่น UUIDs เวอร์ชัน 3 และ 5 ได้อย่างเหมาะสมซึ่งเกินกว่าที่ห้องสมุดของฉัน (เช่น e2fsprogs) ติดตั้งไว้จะสามารถจัดการได้ โชคดีที่ openSUSE มีหนึ่งใน repos หลัก การทำให้รุ่นทำงานโดยใช้ Windows (เช่น Cygwin) หรือ MySQL นั้นล้มเหลว ดูเหมือนว่าถึงเวลาเปลี่ยนเป็น Linux / PostgreSQL / Python (และฉันชอบ SQLyog GUI เป็น MySQL / MariaDB) เนื่องจากฉันต้องการ v3 และ v5 UUID จริงๆ


เห็นด้วยอย่างสมบูรณ์! สำหรับกรณีการใช้งานของฉันมันสมบูรณ์แบบเพราะยังรองรับการกำหนดเนมสเปซผ่าน-v3 ns:URL custom-dataกลไกการสร้าง
Roberto Andrade

1

ฉันแน่ใจว่าบางคนจะมาถึงที่นี่และกำลังมองหาวิธีที่ง่ายในการสร้าง ID เฉพาะสำหรับใช้ในสคริปต์ของพวกเขาและไม่จำเป็นต้องเป็น UUID จริง

หากเป็นเช่นนั้นคุณสามารถทำสิ่งต่อไปนี้ซึ่งจะสร้างรหัสที่ไม่ซ้ำกันจนถึงวินาที - ดังนั้นหากคุณเรียกใช้หลาย ๆ ครั้งภายในไม่กี่วินาทีคุณจะยังได้รับผลลัพธ์เดียวกัน

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

จะสร้างรหัสเช่นต่อไปนี้ตามเวลาปัจจุบันของระบบ:

U1454423662

หมายเหตุ: หากคุณใช้งานบน Linux หรือติดตั้ง Coreutils ไว้ในเครื่อง Mac คุณสามารถใช้สิ่งต่อไปนี้เพื่อสร้างรหัสเฉพาะให้กับนาโนวินาที:

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

หรือหากคุณต้องการโซลูชันที่ใช้ python แบบนาโนวินาทีซึ่งน่าจะใช้ได้เกือบทุกที่ให้รัน:

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

1
นี่เป็นภาพรวมการปฏิบัติที่แย่มาก คอมพิวเตอร์ยุคใหม่มีความสามารถในการทำงานหลายอย่างพร้อมกันและทำงานแบบอนุกรมได้อย่างรวดเร็ว แต่ ID นี้จะเหมือนกันสำหรับการร้องขอใด ๆ ที่อยู่ภายในหนึ่งวินาทีของอีกเครื่องหนึ่ง ไม่ต้องพูดถึงคอมพิวเตอร์เครื่องอื่นที่ใช้งานสคริปต์นี้ในเวลาเดียวกัน ตัวเลือกที่ดี แต่ยังคงไม่ดีจะเป็นเช่นเดียวกับในmktemp -u MYID="$(mktemp -u)"หากคุณสามารถที่จะมีไฟล์ temp ที่ว่างเปล่าวางไว้รอบ ๆ จนกระทั่งรีบูตให้ปล่อย-u:MYID="$(mktemp)"
Chris Harrington

เฮ้ ... คะแนนที่ดีของคะแนนเฉพาะที่สองเท่านั้น ... ฉันจะเพิ่มโน้ตด้านบน ...
Brad Parks

1

หัวข้อนี้ด้วยตัวอย่างที่หลากหลายเป็นประโยชน์กับฉันจริงๆ ฉันต้องการฟังก์ชั่น uuid จากสภาพแวดล้อมที่แตกต่างกันจำนวนมาก และในขณะที่ฉันรักตัวอย่างทุบตีบริสุทธิ์บางครั้งก็สะดวกกว่าที่จะใช้ห้องสมุดจากภาษาอื่น

ดังนั้นเพื่อความทั่วถึง ruby ​​(1.9.3+) มีโมดูล SecureRandom ในตัวที่มีฟังก์ชั่นแฮชและรหัสจำนวนมาก จาก bash cli คุณสามารถทำได้

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
คำอธิบายเพิ่มเติมเล็กน้อยจะช่วยให้คำตอบของคุณ
Dave M

x = od -X -A n /dev/random | head -1 | cut -c3-38 แสดง 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

เดฟเอ็มกลับมาทุบตีหลังจากหลายปีที่ผ่านมานี่เป็นสิ่งที่ฉันรู้ หวังว่ามันจะช่วยได้บ้าง ไชโย, andyfff
andyfff

-1

หากคุณใช้ Java 10

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

Java 10 ไม่ใช่ทุบตี
kasperd

ฉันเพิ่งยกตัวอย่างว่าเขาสามารถสร้าง UUID บนเทอร์มินัลได้เร็วแค่ไหนโดยไม่ต้องใช้โปรแกรมจาวา คนให้ตัวอย่างของการใช้dbus-uuidgenและuuidgen มีอะไรผิดปกติกับการใช้ jshell?
amit

1
@amit ประเด็นก็คือว่าคุณจะต้องให้ตัวอย่างเช่นในกรณีที่jshellสามารถนำมาใช้ในการเขียนสคริปต์ทุบตีและ ไม่ได้เป็นคำสั่งแบบโต้ตอบ นั่นชัดเจนมากในโพสต์ต้นฉบับ
Samveen

ถ้าคุณต้องทำรายการสิ่งที่คุณสามารถทำได้แต่มันเป็นจำนวนมากยาวยืดกว่าecho "System.out.println(java.util.UUID.randomUUID().toString())" | /Library/Java/JavaVirtualMachines/openjdk-11.0.1.jdk/Contents/Home/bin/jshell -s | grep -v ">" uuidgen
mlk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.