Як генерувати дійсну випадкову MAC-адресу з оболонкою bash


17

Як я можу генерувати дійсну випадкову адресу mac з bash.

Перша половина адреси завжди повинна залишатися такою ж

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

просто значення x повинно генеруватися випадковим чином?


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

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


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

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 заснована на функції "printf" C, яка приймає "рядок формату" як перший параметр, а потім додаткові параметри заповнюють рядок формату.
  • % у рядок формату вводить "специфікатор формату", який може бути одним або декількома символами, що вказують, як форматувати аргументи.
  • Провідний нуль (0) у специфікаторі формату означає, що отриманий числовий висновок повинен бути прокладений ведучими нулями до заданої ширини.
  • 2 говорить, що специфікатор повинен відображатися із знаками ширини двох символів.
  • X закінчує специфікатор і позначає, що його слід інтерпретувати як число і відображати як шістнадцятковий. Оскільки це великі регістри, літери af мають бути великими літерами.
  • \ N - це новий рядок - printf інтерпретує звороту косу рису як евакуаційний код, який можна використовувати для відображення інших символів, часто складних символів, таких як новий рядок.
  • Решта символів у специфікаторі формату друкуються буквально, сюди входить початковий "00-06-2F-" та тире між специфікаторами формату.
  • Решта аргументів - це підстановки змінної оболонки (позначаються $) і включають математичний вираз, який є випадковим числом (RANDOM) по модулю 256. Це призводить до випадкового числа між 0 і 255.

2
Як справедливо вказав user58033 у відповіді (яка може бути відсутньою зараз): %02Xдасть одну велику літеру.
Ар’ян

Ах, хороший пункт. Я відзначив, що оригінальне запитання подало приклад, використовуючи верхній регістр. Дякуємо за прийом :-)
Шон Рейфшнайдер

Додатковий +1, якщо ви можете пояснити, що відбувається і чому ваше рішення працює.
Джед Даніельс

Там ти, @Jed.
Шон Рейфшнайдер

17
  1. Створіть відповідний розмір int типу: http://tldp.org/LDP/abs/html/randomvar.html
  2. Перетворити в hex так: 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-широке поле для генерування шістнадцяткових знаків, тому вам не доведеться турбуватися про нульове набивання - підхід змінено для вирішення коментаря.


Додатковий +1, якщо ви надаєте приклад кожному (я знаю, ви вчите його ловити рибу, але ви можете дати йому частинки головоломки, щоб скласти разом, і пояснити, як / чому вони працюють).
Джед Даніельс

@ Джед Даніельс - готово і готово. наданий код.
RobotHumans

Цей код генерує кілька недійсних MAC для мене. Обернувши його в 1000 разів я отримав кілька МОК , як 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Бруно Фінгер

Це було щось, що я викинув туди, оскільки ОП наполягала на ударі. Ви говорите, що не можете зрозуміти, як зафіксувати однозначні цифри нулем? @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 \  -)

може бути найкоротшим з усіх.


Чи можете ви описати у своїй відповіді, що саме робить? Це допоможе використовувати його і іншими способами!
Бруно Бієрі

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циклу in in викликає виведення символу як його числове значення ("A" виводиться як "65"). Дивіться специфікацію POSIX,printf де зазначено:

    Якщо провідним символом є одноцитата або подвійна цитата, значення має бути числовим значенням в базовому кодовому наборі символу, що слідує за одноцитатою або подвійною цитатою.


Здається, потрібно IFS= read …уникати складання 09 0a та 20 (звичайні символи IFS) у 00.
Кріс Джонсен

@Chris: Вибачте, я взяв пару речей, роблячи подвійну перевірку, і забув повернути їх. Це також потрібно -d ''. Я виправлю свою відповідь. Дякую що дали мені знати.
Призупинено до подальшого повідомлення.

На жаль, -rвипало те , що захищає `\`. Я б хотів, щоб правильне поводження з бінарними даними в оболонкових програмах було не настільки вигадливим. Seems Начебто неможливо точно зобразити 00 посередині рядка. Ваш метод однозначного часу обробляє 00 завдяки зручній (розробленій?) Співпраці між read, строповою інтерполяцією та тим, як printfтрактує аргумент "один символ" '. Зітхнути.
Кріс Джонсен

@Chris: Я хотів би, щоб мій процесор 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


Ефективність 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-адрес у моїх сценаріях / середовищі.


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



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

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

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повертає новий тип 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 може бути недоступним у деяких системах;
  • лише малі літери надходять так просто (для отримання великих літер потрібен додатковий крок).

0

Один вкладиш (bash)

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.