Как создать действительный случайный MAC-адрес с помощью оболочки bash
Как я могу сгенерировать действительный случайный MAC-адрес с Bash.
Первая половина адреса всегда должна оставаться такой же
00-60-2F-xx-xx-xx
просто значение х должно генерироваться случайным образом?
15 ответов
В прошлом я делал это используя:
echo 00-60-2F-$[RANDOM%10]$[RANDOM%10]-$[RANDOM%10]$[RANDOM%10]-$[RANDOM%10]$[RANDOM%10]
но это только сделает их в диапазоне 0-9. Для моих целей это было достаточно хорошо.
Вероятно, лучшим решением было бы использовать printf:
printf '00-60-2F-%02X-%02X-%02X\n' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256]
Вот как это работает:
- Программа printf основана на функции C "printf", которая принимает "строку формата" в качестве первого параметра, а затем дополнительные параметры заполняют строку формата.
- % в строке формата вводит "спецификатор формата", который может быть одним или несколькими символами, указывающими, как форматировать аргументы.
- Ведущий ноль (0) в спецификаторе формата означает, что результирующий числовой вывод должен быть дополнен начальными нулями до указанной ширины.
- 2 говорит о том, что спецификатор должен отображаться с шириной в два символа.
- X завершает спецификатор и обозначает, что он должен интерпретироваться как число и отображаться как шестнадцатеричное число. Поскольку это прописные буквы, буквы af должны быть заглавными.
- \ N - это новая строка - printf интерпретирует обратную косую черту как escape-код, который можно использовать для отображения других символов, часто сложных символов, таких как новая строка.
- Остальные символы в спецификаторе формата распечатываются буквально, включая начальные "00-06-2F-" и тире между спецификаторами формата.
- Остальные аргументы являются подстановочными переменными оболочки (обозначаемыми $) и включают математическое выражение, которое является случайным числом (СЛУЧАЙНО) по модулю 256. Это приводит к случайному числу от 0 до 255.
Вот рыба.
Этот сценарий оболочки сгенерирует случайную строку, которую вы ищете:
#!/bin/bash
hexchars="0123456789ABCDEF"
end=$( for i in {1..6} ; do echo -n ${hexchars:$(( $RANDOM % 16 )):1} ; done | sed -e 's/\(..\)/-\1/g' )
echo 00-60-2F$end
У меня просто было кое-что здесь, которое показывало, как запустить его из командной строки, но после того, как я посмотрел на извилистое (но одобренное) решение Денниса Уильямсона, я понял, что люди ожидают ответа, в котором им не нужно ничего делать самих себя.
- Создайте int соответствующего размера, например, так: http://tldp.org/LDP/abs/html/randomvar.html
- Преобразовать в шестнадцатеричный код, например, так: http://snipplr.com/view/2428/convert-from-int-to-hex/
- Добавьте тире между тремя случайно сгенерированными кусками
#!/bin/bash
RANGE=255
#set integer ceiling
number=$RANDOM
numbera=$RANDOM
numberb=$RANDOM
#generate random numbers
let "number %= $RANGE"
let "numbera %= $RANGE"
let "numberb %= $RANGE"
#ensure they are less than ceiling
octets='00-60-2F'
#set mac stem
octeta=`echo "obase=16;$number" | bc`
octetb=`echo "obase=16;$numbera" | bc`
octetc=`echo "obase=16;$numberb" | bc`
#use a command line tool to change int to hex(bc is pretty standard)
#they're not really octets. just sections.
macadd="${octets}-${octeta}-${octetb}-${octetc}"
#concatenate values and add dashes
echo $macadd
#echo result to screen
#note: does not generate a leading zero on single character sections. easily remediedm but that's an exercise for you
Или в питоне:
from random import randint
def gen_mac_char():
return hex((randint(0,16))).split('x')[1]
def gen_mac_pair():
return ''.join([gen_mac_char(), gen_mac_char()])
def gen_last_half_mac(stem):
return '-'.join([stem, gen_mac_pair(), gen_mac_pair(), gen_mac_pair()])
print(gen_last_half_mac('00-60-2F'))
Обратите внимание, что версия Python использует только поле шириной 16 для генерации шестнадцатеричного символа, так что вам не нужно беспокоиться о заполнении нулями - подход исправлен с учетом комментария.
Используя стандартные инструменты, либо
# output in capitals
hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/random
или же
# output in lower case letters
echo 00-60-2f$(od -txC -An -N3 /dev/random|tr \ -)
может быть самым коротким из всех.
#!/bin/bash
LC_CTYPE=C
MAC=00-60-2F
for i in {1..3}
do
IFS= read -d '' -r -n 1 char < /dev/urandom
MAC+=$(printf -- '-%02x\n' "'$char")
done
printf '%s\n' "$MAC"
Ключи к тому, как это работает:
LC_CTYPE=C
- позволяет символы> 0x7FIFS=
- отключает интерпретацию\t
(Закладка),\n
(новая строка) и пробел-d ''
- позволяет переводить строки-r
позволяет\
(и почти всегда должен использоваться по привычкеread
)- Спецификатор формата
-%02x\n
заставляет вывод быть буквальным дефисом, за которым следует двузначное шестнадцатеричное число, включая, если необходимо, начальный ноль. Новая строка здесь избыточна и может быть опущена. read
получает один байт (-n 1
) от/dev/urandom
в диапазоне от 0 до 255 (00
вFF
).Одиночная цитата в последнем аргументе
printf
в цикле символ выводится как его числовое значение ("A" выводится как "65"). Смотрите спецификацию POSIX дляprintf
где сказано:Если начальный символ представляет собой одинарную или двойную кавычку, значение должно быть числовым значением в базовом наборе символов, следующего за одинарной или двойной кавычкой.
Самый короткий способ, которым я мог придумать, - это использовать hexdump напрямую.
echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
- -n3 говорит hexdump прочитать три байта
- Строка формата печатает тире и двухзначное шестнадцатеричное значение для каждого байта
- "/1" означает применять формат для каждого прочитанного байта
- "-%02X" - это спецификация printf для печати начального нуля, двухзначного шестнадцатеричного значения в верхнем регистре
- / dev / random - исходные случайные байты
Протестировано на GNU/Linux
Еще одно решение
$ echo '00 60 2f'$(od -An -N3 -t xC /dev/urandom) | sed -e 's/ /-/g'
То же самое в верхнем регистре
$ echo '00 60 2f'$(od -An -N3 -t xC /dev/urandom) | sed -e 's/ /-/g' | tr '[:lower:]' '[:upper:]'
Сгенерируйте его для переменной среды Bash
$ export MAC=$(echo '00 60 2f'$(od -An -N3 -t xC /dev/urandom) | sed -e 's/ /-/g')
$ echo $MAC
Подробности:
od (восьмеричный дамп)
-An
Подавляет лидирующее представление адреса (дополнительный шум) вывода.-N3
Ограничьте вывод тремя байтами.-t xC
Выведите в шестнадцатеричном виде, ASCII стиль символов, по желанию./dev/urandom
Псевдофайл случайного числа ядра Linux.sed (редактор потоков) Для замены пробела на пробел.
-e <SCRIPT>
выполнить сценарий sed.tr (перевод строки) Необязательно, в этом примере. Мне нравятся прописные MAC-адреса в моих скриптах / окружении.
#!/bin/bash
#Creates an array containing all hexadecimal characters
HEX=(a b c d e f 0 1 2 3 4 5 6 7 8 9)
#Defines MAC string length as 0 (total SL will be 17)
SL=0
#Loop sequentially assigns random hex characters in pairs until a full
#MAC address is generated.
while [ $SL -lt 17 ]
do
num=`shuf -i 0-15 -n 1` #Generates random number which will be used as array index
RMAC="$RMAC""${HEX[$num]}" #Uses the randomly generated number to select a hex character
num=`shuf -i 0-15 -n 1` #New random number
RMAC="$RMAC""${HEX[$num]}" #Appends second hex character
SL=$[`echo $RMAC | wc -c` - 1] #Calculates SL and stores in var SL
if [ $SL -lt 17 ] #If string is uncomplete, appends : character
then
RMAC=""$RMAC":"
fi
done
echo $RMAC #Displays randomly generated MAC address
Это должно работать
echo 00-60-2f-`openssl rand -hex 3 | sed 's/\(..\)/\1-/g; s/.$//'`
Один лайнер (баш)
mac=$(c=0;until [ $c -eq "6" ];do printf ":%02X" $(( $RANDOM % 256 ));let c=c+1;done|sed s/://)
результат
$ echo $mac
93:72:71:0B:9E:89
end=$( echo $RANDOM | openssl md5 | sed 's/\(..\)/\1-/g' | cut -b-8 )
echo 00-60-2f-$end
Это работает в классической оболочке (#!/bin/sh
) скрипт:
random_mac() {
printf '%.2x\n' "$(shuf -i 0-281474976710655 -n 1)" | sed -r 's/(..)/\1:/g' | cut -d: -f -6
}
Или, если вы хотите иметь собственный префикс:
random_mac_with_prefix() {
echo -n "00:60:2f:" &&
printf '%.2x\n' "$(shuf -i 0-281474976710655 -n 1)" | sed -r 's/(..)/\1:/g' | cut -d: -f -3
}
Пример использования:
$ random_mac
96:ef:45:28:45:25
$ random_mac
7e:47:26:ae:ab:d4
$ random_mac_with_prefix
00:60:2f:24:f4:18
$ random_mac_with_prefix
00:60:2f:63:08:b2
В Linux:
printf '00-60-2f-' && cut -b 7-11,24-26 /proc/sys/kernel/random/uuid
Объяснение:
В линуксе /proc/sys/kernel/random/uuid
возвращает новый тип 4 (случайный) UUID каждый раз, когда вы читаете его. Большинство его символов - (псевдо) случайные шестнадцатеричные цифры, поэтому мы можем их использовать. Например:
$ cat /proc/sys/kernel/random/uuid
5501ab12-b530-4db5-a8ea-3df93043f172
$ # ^ ^ Beware, these characters are not random.
$ # ^^^^^ ^^^ Let's use characters on these positions.
$ cut -b 7-11,24-26 /proc/sys/kernel/random/uuid
6d-74-a1
$ cut -b 7-11,24-26 /proc/sys/kernel/random/uuid
13-f9-75
Теперь достаточно напечатать 00-60-2f-
(без перевода строки) сначала:
$ printf '00-60-2f-' && cut -b 7-11,24-26 /proc/sys/kernel/random/uuid
00-60-2f-86-f9-21
Плюсы:
- шестнадцатеричные цифры с самого начала, конверсия / фильтрация не требуются;
printf
а такжеcut
инструменты POSIX;- (для вашего конкретного случая) дефисы уже в UUID, мы их используем.
Минусы:
- нам нужно учитывать две неслучайные цифры в UUID;
/proc/sys/kernel/random/uuid
может быть недоступно в некоторых системах;- так просты только строчные буквы (вам нужен дополнительный шаг, чтобы получить заглавные буквы).
Другой вариант заключается в использовании jot
:
echo 00-60-2F-$(jot -w%02X -s- -r 3 0 256)
-w
меняет формат, -s
меняет разделитель и -r
генерирует случайные числа.
Команды, использующие od
в ответах artistoex и zero2cx добавьте дополнительные черточки к выходу с OS X od
, но это не так:
echo 00-60-2f-$(od -tx1 -An -N3 /dev/random|awk '$1=$1'|tr \ -)
OS X's od
(/usr/bin/od
ниже) использует другой формат вывода, чем GNU od
:
$ /usr/bin/od -N3 -tx1 -An /dev/random|tr ' ' -
-----------c7--fd--55----------------------------------------------------
$ god -N3 -tx1 -An /dev/random|tr ' ' -
-94-9e-5c
Этот тоже работает. Вывод все в верхнем регистре, как требуется.
openssl rand -hex 3 | sed 's/\(..\)\(..\)\(..\)/00-60-2F-\1-\2-\3/' | tr [a-f] [A-F]