Как создать действительный случайный MAC-адрес с помощью оболочки bash

16

Как я могу сгенерировать действительный случайный MAC-адрес с Bash.

Первая половина адреса всегда должна оставаться такой же

00-60-2F-xx-xx-xx

просто значение х должно генерироваться случайным образом?

NES
источник
10
echo -n 00-60-2F; dd bs=1 count=3 if=/dev/random 2>/dev/null |hexdump -v -e '/1 "-%02X"'
artistoex
1
@artistoex Это было прекрасно ... Почему ты не опубликовал это как ответ?
bobmagoo

Ответы:

18

Вот рыба.

Этот сценарий оболочки сгенерирует случайную строку, которую вы ищете:

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

У меня просто было кое-что, что показывало, как запустить его из командной строки, но, посмотрев на извилистое (но одобренное) решение Денниса Уильямсона, я вижу, что люди ожидают ответа, в котором им не нужно делать никакой работы. самих себя.

deltaray
источник
спасибо, что понял, что я пытался научить его ловить рыбу вместо того, чтобы кормить ее ложкой
RobotHumans
1
Вы всегда можете объяснить свой ответ так, чтобы вы оба учили его ловить рыбу в дополнение к обеспечению на этот раз ...
Джед Дэниелс
Этот сценарий работает значительно быстрее, чем предложенный hbdgaf, и не генерирует недопустимый MAC-адрес в цикле 1000 раз. Благодарность!
Бруно Фингер
1
Ваше решение работает и имеет только 3 строки. Я продан.
Ричард Гомес
17

В прошлом я делал это используя:

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.
Шон Рейфшнайдер
источник
2
Как справедливо указал пользователь 58033 в ответе (который мог бы исчезнуть сейчас): %02Xдал бы одну заглавную букву.
Арьян
Ах, хорошая мысль. Я сделал интервал между тем, что первоначальный вопрос дал пример с использованием заглавных букв. Спасибо за прием. :-)
Шон Рейфшнайдер
Дополнительные +1, если вы можете объяснить, что происходит и почему ваше решение работает.
Джед Дэниелс
Ну вот, @Jed.
Шон Рейфшнейдер,
17
  1. Создайте int соответствующего размера, например, так: http://tldp.org/LDP/abs/html/randomvar.html
  2. Преобразовать в шестнадцатеричный код, например, так: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Добавьте тире между тремя случайно сгенерированными кусками
#!/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 для генерации шестнадцатеричного символа, так что вам не нужно беспокоиться о заполнении нулями - подход исправлен с учетом комментария.

RobotHumans
источник
Дополнительные +1, если вы приведете пример каждого из них (я знаю, что вы учите его ловить рыбу, но вы можете дать ему кусочки головоломки, чтобы собрать их вместе, и объяснить, как / почему они работают).
Джед Дэниелс
@ Джед Дэниелс - сделано и сделано. код предоставляется.
RobotHumans
Этот код генерирует несколько недопустимых MAC для меня. Обернув его в 1000 раз я получил несколько МОК , как 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Бруно Фингер
Это было просто что-то, что я выкинул, так как OP настаивал на bash. Вы говорите, что не можете понять, как дополнить одну цифру нулем, верно? @BrunoFinger
RobotHumans,
Может быть легко переработан для использования 16 вместо 255 и создания нулевого заполнителя. Это просто больше строк ...
RobotHumans
12

Используя стандартные инструменты, либо

# 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 \  -)

может быть самым коротким из всех.

artistoex
источник
Можете ли вы описать в своем ответе, что конкретно делает Од? Это помогло бы использовать его и другими способами!
Бруно Биери
7
#!/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 - разрешает символы> 0x7F
  • IFS=- отключает интерпретацию \t(табуляции), \n(новой строки) и пробела
  • -d ''- позволяет переводить строки
  • -rпозволяет \(и почти всегда должен использоваться по привычке read)
  • Спецификатор формата -%02x\nприводит к тому, что вывод будет буквальным дефисом, за которым следует двузначное шестнадцатеричное число, включая, если необходимо, начальный ноль. Новая строка здесь лишняя и может быть опущена.
  • readПолучает один байт ( -n 1) от /dev/urandomв диапазоне от 0 до 255 ( 00к FF).
  • Одиночная кавычка в последнем аргументе printfв цикле приводит к выводу символа в виде его числового значения («A» выводится как «65»). Смотрите спецификацию POSIX,printf где сказано:

    Если начальный символ представляет собой одинарную или двойную кавычку, значение должно быть числовым значением в базовом наборе символов, следующего за одинарной или двойной кавычкой.

Приостановлено до дальнейшего уведомления.
источник
Кажется, нужно IFS= read …избегать складывания 09 0a и 20 (обычные символы IFS) в 00.
Крис Джонсен
@Chris: Извините, я взял пару вещей, делая двойную проверку и забыл положить их обратно. Это также необходимо -d ''. Я исправлю свой ответ. Спасибо, что дали мне знать.
Приостановлено до дальнейшего уведомления.
Ой, то -rчто защищает `\` поссорилось. Я бы хотел, чтобы правильная обработка двоичных данных в программах оболочки была не такой сложной. Seems Кажется невозможным точно представить 00 в середине строки. Ваш односимвольный метод обрабатывает 00 в силу удобного (разработанного?) Взаимодействия между read, интерполяции строк и того, как printfобрабатывается односимвольный аргумент '. Вздох.
Крис Джонсен
@ Крис: Хотелось бы, чтобы мой процессор DWIM не был на фрите. Кстати, вам может быть интересно увидеть написанный мной чистый Bash-скрипт, который дублирует основные функции hexdump -C.
Приостановлено до дальнейшего уведомления.
Дополнительные +1, если вы можете объяснить, что происходит и почему ваше решение работает.
Джед Дэниелс
7

Самый короткий способ, которым я мог придумать, - это использовать hexdump напрямую.

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3 говорит hexdump прочитать три байта
  • Строка формата печатает тире и двухзначное шестнадцатеричное значение для каждого байта
    • «/ 1» означает применять формат для каждого прочитанного байта
    • «-% 02X» - это спецификация printf для печати начального нуля, двухзначного шестнадцатеричного значения в верхнем регистре
  • / dev / random - исходные случайные байты

Протестировано на GNU / Linux

maxthoursie
источник
Эффективность Unix на работе :-)
artistoex
hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/randomнемного короче :-)
artistoex
4

Еще одно решение

$ 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-адреса в моих скриптах / окружении.

zero2cx
источник
2
#!/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
Гематома
источник
2

Это должно работать

echo 00-60-2f-`openssl rand -hex 3 | sed 's/\(..\)/\1-/g; s/.$//'`
linuxrules94
источник
0
end=$( echo $RANDOM | openssl md5 | sed 's/\(..\)/\1-/g' | cut -b-8 )
echo 00-60-2f-$end
Кевин Дютерн
источник
5
Дополнительные +1, если вы можете объяснить, что происходит и почему ваше решение работает.
Джед Дэниелс
0

Этот тоже работает. Вывод все в верхнем регистре, как требуется.

openssl rand -hex 3 | sed 's/\(..\)\(..\)\(..\)/00-60-2F-\1-\2-\3/' | tr [a-f] [A-F]
Ярослав Кучера
источник
0

Это работает в классическом #!/bin/shсценарии shell ( ):

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
kvaps
источник
0

Другой вариант заключается в использовании 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 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
nisetama
источник
1
Осторожно с Джотом. У меня есть несколько созданных таким образом макинтош, в которых есть "100", например, 00-60-2F-100-A3-F6 ...
petrus
@petrus Вы правы, я отредактировал ответ, чтобы изменить jot -w%02X -s- -r 3 1 256на jot -w%02X -s- -r 3 0 256.
Нисетама
0

В Linux:

printf '00-60-2f-' && cut -b 7-11,24-26 /proc/sys/kernel/random/uuid

Объяснение:

В Linux каждый раз при чтении выдает/proc/sys/kernel/random/uuid новый UUID типа 4 (случайный) . Большинство его символов - (псевдо) случайные шестнадцатеричные цифры, поэтому мы можем их использовать. Например:

$ 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 может быть недоступно в некоторых системах;
  • так просты только строчные буквы (вам нужен дополнительный шаг, чтобы получить заглавные буквы).
Камил Мачоровский
источник
0

Один лайнер (баш)

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
Zibri
источник