Как создать UUID в Bash?
14 ответов
Увидеть uuidgen
Программа, которая является частью пакета e2fsprogs.
Согласно этому, libuuid
сейчас является частью util-linux, и включение в e2fsprogs постепенно прекращается. Тем не менее, на новых системах Ubuntu, uuidgen
сейчас в uuid-runtime
пакет.
Чтобы создать uuid и сохранить его в переменной:
uuid=$(uuidgen)
В моей системе Ubuntu буквенные символы выводятся в нижнем регистре, а в моей системе OS X - в верхнем (спасибо Дэвиду за то, что он указал это в комментарии).
Чтобы переключиться на весь верхний регистр (после генерации, как указано выше):
uuid=${uuid^^}
Чтобы переключиться на все строчные буквы:
uuid=${uuid,,}
Если, например, у вас есть два UUID и вы хотите сравнить их в Bash, игнорируя их регистр, вы можете сделать tolower()
сравнение стилей вот так:
if [[ ${uuid1,,} == ${uuid2,,} ]]
Чтобы добавить разнообразие без добавления внешних зависимостей, в Linux вы можете сделать:
UUID=$(cat /proc/sys/kernel/random/uuid)
Чтобы распространять плохие практики, во FreeBSD, под уровнем совместимости с linux (linuxulator?),
UUID=$(cat /compat/linux/proc/sys/kernel/random/uuid)
Рекомендации:
Просто для полноты... Есть также генератор UUID, установленный с dbus
пакет на Debian. Я пропустил это, оглядываясь раньше. Вероятно, это тот же алгоритм, что и в пакете e2fsprogs, но он не добавляет тире, поэтому он может быть немного чище для вас:
$ uuidgen
387ee6b9-520d-4c51-a9e4-6eb2ef15887d
$ dbus-uuidgen
d17b671f98fced5649a856a54b51c9e6
Grawity добавляет совет по безопасности: "UUID DBus не связаны или не совместимы с RFC 4122. Кроме того, dbus-uuidgen всегда использует метку времени Unix в качестве последних 4 байтов. Поэтому они могут быть неподходящими для некоторых применений". (Спасибо, Гравити, я должен был это заметить на странице руководства.)
Если вы не хотите зависеть от других исполняемых файлов или не можете их использовать, здесь приведена чистая версия 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
Я нашел этот скрипт "однострочным" полезным, когда 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 и новее. Мне любопытно, не склонен ли он к уникальности, но за последние 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-12
строчные буквы a-f0-9
,
993bb8d7-323d-b5ee-db78-f976a59d8284
Просто чтобы питон не чувствовал себя обделенным:
python -c 'import uuid; print uuid.uuid1()'
2d96768e-02b3-11df-bec2-001e68b9d147
Чтобы использовать его в оболочке:
myvar=$(python -c 'import uuid; print uuid.uuid1()')
Посмотрите UUID Документации Python для типов UUIDS, которые могут быть сгенерированы.
Чтобы сгенерировать системный ID, совместимый с идентификатором компьютера, на компьютере, отличном от systemd, вы можете использовать python для этого:
python -c 'import re; import uuid; print re.sub("-","",str(uuid.uuid4()))' \
> /etc/machine-id
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
Это было бы тривиально, чтобы добавить к шеллскрипту с обратными чертами или $()
обозначения:
#!/bin/bash
# ...do some stuff
$myvar = $(perl -e 'use UUID; UUID::generate($uuid); UUID::unparse($uuid, $string); print "$string";')
# ...do some more stuff
Я написал небольшую функцию 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"')]))'
Эта тема с ее разнообразными примерами была очень полезна для меня. Мне часто нужны функции uuid из разных сред. И хотя мне нравятся чистые примеры bash, иногда удобнее использовать библиотеку на другом языке.
Так что для большей полноты, ruby (1.9.3+) имеет встроенный модуль SecureRandom, содержащий ряд полезных хеш-функций и функций id. Вы можете сделать это из Bash Cli.
ruby -r securerandom -e 'puts SecureRandom.uuid'
Я уверен, что некоторые прибудут сюда и просто ищут простой способ создания уникального идентификатора для использования в своих сценариях, и он не должен быть истинным 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
Пожалуйста, посмотрите на библиотеку OSSP UUID ( http://www.ossp.org/pkg/lib/uuid/) и рассмотрите возможность ее установки. Некоторые проекты предлагают его в качестве опции (например, PostgreSQL). Он правильно обрабатывает UUID версии 3 и версии 5, что было выше того, что могла обработать моя установленная (например, e2fsprogs) библиотека. К счастью, openSUSE имеет его в одном из основных репозиториев. Получение версии для работы с Windows (например, Cygwin) или MySQL было непростым делом. Похоже, пришло время переключиться на Linux/PostgreSQL/Python (и мне так понравился графический интерфейс SQLyog для MySQL/MariaDB), поскольку мне действительно нужны UUID v3 и v5.
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`
Если вы используете Java 10.
$ jshell
jshell> import java.util.*
jshell> String id = UUID.randomUUID().toString();