如何在bash中创建UUID?


185

在Java中,可以创建一个随机的UUID

UUID uuid = UUID.randomUUID();

如何在Bash中做到这一点?

Answers:


225

uuidgen程序,其是一部分的e2fsprogs包。

根据这个libuuid现在是一部分的util-linux的并且包含在e2fsprogs的将被淘汰。但是,在新的Ubuntu系统上,uuidgen该文件uuid-runtime包中已包含该文件。

要创建一个uuid并将其保存在变量中:

uuid=$(uuidgen)

在我的Ubuntu系统上,字母字符输出为小写字母,而在我的OS X系统上,字母字符输出为大写字母(感谢David在注释中指出了这一点)。

要切换到所有大写字母(如上生成后):

uuid=${uuid^^}

切换到所有小写字母:

uuid=${uuid,,}

例如,如果您有两个UUID,并且想要在Bash中比较它们,而忽略它们的大小写,则可以tolower()进行如下样式比较:

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

7
嘿,不公平!我的e2fsprogs没有附带!我想要一个,我在哪里买?(更新:啊……... debian uuid-runtime毫无理由地将其
粘贴

uuidgen内置在freeBSD中。它并不总是在e2fsprogs软件包中。
好人2014年

1
@Rob:要回答您的原始问题,它用于驱动器标签
丹尼斯·威廉姆森

2
我注意到Mac上的uuidgen都以大写形式发出,而在Ubuntu上(util-linux 2.20.1中的uuidgen)以小写形式发出。为什么会有所不同?Ubuntu也列出了该工具的来源,但在Mac上,没有版本信息,也没有提供它的软件包。
戴维(David)

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
这太棒了。
汤姆·奥康纳

3
应该避免这种情况,因为它是高度不可移植的(尽管FreeBSD为编写不良的应用程序提供了/ compat / linux / proc / sys / kernel / random / uuid)
好人2014年

1
它非常适合initrd图像内部使用
Maximilian

2
这应该是最好的答案!
dguerri

6
对于真正最少的设置(例如Docker容器),这是一个更好的答案。
jacderida

34

只是为了完整起见... dbusDebian 上还安装了一个UUID生成器。我很早就错过了它。它可能与e2fsprogs软件包使用相同的算法,但是它没有添加破折号,因此对您来说可能更干净一些:

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

$ dbus-uuidgen
d17b671f98fced5649a856a54b51c9e6

Grawity增加了一个安全提示:“ DBus UUID与RFC 4122不相关或不兼容。此外,dbus-uuidgen始终使用Unix时间戳作为最后4个字节。因此,它们可能不适用于某些用途。” (谢谢,Grawity,我应该在联机帮助页中发现了这一点。)


7
DBus UUID与RFC 4122不相关或不兼容。此外,dbus-uuidgen始终使用Unix时间戳作为最后4个字节。因此,它们可能不适用于某些用途。
grawity 2010年

Fedora-25上也有同样的作品……
kmonsoor

20

如果你不希望依赖于其他可执行文件,也可以不使用它们,这里是从纯bash的版本在这里

# 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如果需要,可以在单独的行中分解)。
丹尼斯·威廉姆森

1
我在github链接的代码中添加了注释,显示了case用于消除if语句以及内部for语句的版本。它使代码更加整洁。请注意,两者B%15都应为B%16B%255应该为B%256
丹尼斯·威廉姆森

将其放在某个网址上,以便人们可以获取它并尝试使用它 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及更高版本上进行了成功测试。我很想知道这是否容易造成非唯一性,但是我在过去的十年中没有被“咬”过。当然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-12小写字符的模式a-f0-9

993bb8d7-323d-b5ee-db78-f976a59d8284

1
辉煌!仅一行,没有依赖项,与BSD / macOS兼容...很棒
dinigo

千万不要使用“尾-1”。如果仅运行“ od -x / dev / urandom”,它将无限期地继续运行,从而连续产生更多行的随机数据。“ tail -1”可能永远坐在那里,等待“最后一条”线。否则,这是一个很好的解决方案。
UncaAlby

请注意,当head输出的行数大于1时,tail仅在“ explanation”中作为可选参数。此处确保awk接收一行16字节的单行,这不是原始命令的一部分。从od到头的管道已经对管道到尾部-1的输出进行了消毒。以我的经验,尾部永远等待的唯一时间是使用-f参数。抱歉,如果解释不清楚,指出只有在head的输出产生多行时才需要使用tail -1。

2
千万不能使用此,它完全违反了UUID规范。这样,仅版本4 UUID可以是随机的。
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不会感到被遗忘:

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

在外壳中使用它:

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

有关可以生成的UUIDS的类型,请参见Python文档UUID

要在非系统机器上生成与系统机器ID兼容的文件,可以使用python这样做:

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

uuid是内置的吗?
亚历山大·米尔斯

python曾经工作过吗?我得到这个`File“ <string>”,第1行import uuid; 打印uuid.uuid1()^ SyntaxError:语法无效
Alexander Mills

1
使用python3 -c "import uuid; print(uuid.uuid4())"的python3
abdusco

11

Perl提供了基于该e2fsprogs软件包的UUID库。在我的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中将是微不足道的:

#!/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 2011年


1

我使用Python编写了一个小Bash函数来批量生成任意数量的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)。 它可以正确处理版本3和版本5 UUID,这超出了我已安装(例如e2fsprogs)库的处理能力。幸运的是,openSUSE在主存储库之一中提供了它。使用Windows(例如Cygwin)或MySQL来运行版本一直失败。看起来是时候切换到Linux / PostgreSQL / Python了(我非常喜欢将SQLyog GUI转换为MySQL / MariaDB),因为我确实需要v3和v5 UUID。


完全同意!在我的用例中,它非常完美,因为它还通过-v3 ns:URL custom-data种子机制支持命名空间。
罗伯托·安德拉德

1

我确定有些人会到达这里,只是在寻找一种简单的方法来生成用于其脚本的唯一ID,而不必是真正的UUID。

如果是这样,您可以执行以下操作,这将生成一个唯一的ID,直到秒为止。-因此,如果在一秒钟内多次运行此ID,您仍将获得相同的结果。

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

将根据当前系统时间生成如下所示的ID:

U1454423662

注意:如果您使用的是Linux,或者在Mac上安装了Coreutils,则可以使用以下代码生成纳秒级的唯一ID:

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

或者,如果您希望使用基于python的解决方案,该解决方案几乎可以在任何地方都可以工作,请运行以下命令:

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

1
总体而言,这是非常糟糕的做法。现代计算机完全能够并行运行许多事物并快速完成串行任务,但是此ID对于在一秒钟之内的任何调用将是相同的。更不用说同时运行此脚本的任何其他计算机。更好但仍然不是更好的选择mktemp -uMYID="$(mktemp -u)"。如果您有足够的时间放置空的临时文件直到重新启动,请删除-uMYID="$(mktemp)"
Chris Harrington

嘿...第二点唯一的优点...我将在上面添加一些说明...
布拉德·帕克斯

1

这个线程,包括各种各样的例子,对我真的很有用。我经常需要来自许多不同环境的uuid函数。虽然我喜欢纯bash示例,但有时使用其他语言的库会更方便。

因此,仅出于透彻考虑,ruby(1.9.3+)具有内置的SecureRandom模块,其中包含许多有用的hash和id函数。在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 给你这个回声低于$ 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 回声$ UUID 4151540a-1f7d0bef-8a07-25fbd26183a3
andyfff

戴夫·M(Dave M),在离开许多年后重返bash,这在我目前的知识领域尚处于边缘。希望将其分解会有所帮助。干杯,andyfff
andyfff

-1

如果您使用的是Java 10。

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

Java 10不是bash。
kasperd

我只是举了一个例子,说明了他如何在不运行Java程序的情况下在终端上快速生成UUID。人们给出了使用dbus-uuidgenuuidgen的示例。使用jshell有什么问题?
艾米特

1
@amit的要点是,您需要给出一个jshell可以在bash脚本中使用不是作为交互式命令的示例。这在原始帖子中非常清楚。
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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.