วิธีสร้างที่อยู่ MAC แบบสุ่มที่ถูกต้องด้วย bash shell


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

ฉันเพิ่งมีบางอย่างที่นี่ซึ่งแสดงวิธีเรียกใช้จากบรรทัดคำสั่ง แต่หลังจากดูวิธีแก้ปัญหาที่ซับซ้อน (แต่ upvoted) ของ Dennis Williamson ฉันเห็นว่าคำตอบที่คนคาดหวังคือสิ่งที่พวกเขาไม่ต้องทำงานใด ๆ ตัวเอง


ขอบคุณสำหรับการตระหนักว่าฉันพยายามทำให้เขาเรียนรู้การตกปลาแทนที่จะใช้วิธีตักช้อน
RobotHumans

1
คุณสามารถอธิบายคำตอบของคุณได้ตลอดเวลาเพื่อที่คุณจะได้สอนเขาถึงวิธีการตกปลาพร้อมทั้งให้เวลากับเขาในครั้งนี้ ...
Jed Daniels

สคริปต์นี้จะทำงานมากมากเร็วกว่าหนึ่งที่เสนอโดย hbdgaf และไม่สร้างใด ๆ ที่อยู่ MAC ไม่ถูกต้องในครั้งห่วง 1000 ขอบคุณ!
Bruno Finger

1
โซลูชันของคุณใช้งานได้และมีเพียง 3 บรรทัด ฉันขายแล้ว
Richard Gomes

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" ซึ่งใช้ "format string" เป็นพารามิเตอร์แรกจากนั้นพารามิเตอร์เพิ่มเติมจะเติมในสตริงรูปแบบ
  • % ในสตริงรูปแบบแนะนำ "ตัวระบุรูปแบบ" ซึ่งอาจเป็นอักขระอย่างน้อยหนึ่งตัวที่บอกวิธีจัดรูปแบบอาร์กิวเมนต์
  • ศูนย์นำหน้า (0) ในตัวระบุรูปแบบหมายความว่าผลลัพธ์ตัวเลขผลลัพธ์ควรถูกเสริมด้วยศูนย์นำหน้าจนถึงความกว้างที่ระบุ
  • ที่ 2 บอกว่าตัวระบุควรจะแสดงโดยใช้ความกว้างของอักขระสองตัว
  • X สิ้นสุดตัวระบุและแสดงว่าควรตีความเป็นตัวเลขและแสดงเป็นเลขฐานสิบหก เนื่องจากเป็นตัวพิมพ์ใหญ่ตัวอักษร af จึงควรเป็นตัวพิมพ์ใหญ่
  • \ n เป็นบรรทัดใหม่ - printf ตีความแบ็กสแลชเป็นรหัส Escape ซึ่งสามารถใช้เพื่อแสดงอักขระอื่น ๆ ซึ่งมักจะเป็นอักขระที่มีเล่ห์เหลี่ยมเหมือนขึ้นบรรทัดใหม่
  • อักขระที่เหลือในตัวระบุรูปแบบจะถูกพิมพ์ออกมาอย่างแท้จริงซึ่งรวมถึง "00-06-2F-" เริ่มต้นและขีดกลางระหว่างตัวระบุรูปแบบ
  • อาร์กิวเมนต์ที่เหลือคือการแทนที่ตัวแปรเชลล์ (แทนด้วย $) และรวมถึงนิพจน์ทางคณิตศาสตร์ซึ่งเป็นตัวเลขสุ่ม (RANDOM) modulo 256 ซึ่งจะส่งผลให้ตัวเลขสุ่มระหว่าง 0 ถึง 255

2
ในฐานะที่เป็นuser58033ชี้ให้เห็นอย่างถูกต้องในคำตอบ (ซึ่งอาจหายไปในขณะนี้): %02Xจะให้ตัวอักษรตัวพิมพ์ใหญ่หนึ่งตัว
Arjan

อ่าจุดดี ฉันเว้นระยะที่คำถามเดิมให้ตัวอย่างโดยใช้ตัวพิมพ์ใหญ่ ขอบคุณสำหรับการต้อนรับ :-)
Sean Reifschneider

+1 เพิ่มเติมหากคุณสามารถอธิบายสิ่งที่เกิดขึ้นและสาเหตุที่โซลูชันของคุณทำงาน
Jed Daniels

คุณไปแล้ว @Jed
Sean Reifschneider

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'))

โปรดทราบว่าเวอร์ชันของไพ ธ อนใช้ฟิลด์ที่มีความกว้างเพียง 16 เพื่อสร้าง hex char ดังนั้นคุณไม่ต้องกังวลเกี่ยวกับการเติมเต็มศูนย์ - วิธีการแก้ไขเพื่อแก้ไขความคิดเห็น


+1 พิเศษหากคุณยกตัวอย่างของแต่ละอัน (ฉันรู้ว่าคุณกำลังสอนเขาเกี่ยวกับการตกปลา แต่คุณสามารถให้ชิ้นส่วนของปริศนาเพื่อรวมเข้าด้วยกันและอธิบายว่าทำไมพวกเขาถึงทำงาน)
Jed Daniels

@Jed Daniels - ทำและทำเสร็จแล้ว รหัสที่ให้ไว้
RobotHumans

รหัสนี้กำลังสร้าง MAC ที่ไม่ถูกต้องสำหรับฉัน วนลูปมัน 1000 ครั้งผมได้แม็คไม่กี่ชอบ00-60-2F-8B-5-2C, ,00-60-2F-A-71-97 00-60-2F-82-F1-4
Bruno Finger

มันเป็นเพียงสิ่งที่ฉันขว้างออกไปที่นั่นตั้งแต่ OP ได้ยืนยันในการทุบตี คุณกำลังบอกว่าคุณไม่สามารถหาตัวเลขที่เป็นศูนย์ได้ด้วยวิธีที่ถูกต้อง @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 \  -)

อาจจะสั้นที่สุดของทั้งหมด


คุณสามารถอธิบายในคำตอบของคุณว่าทำอะไรได้บ้าง? มันจะช่วยในการใช้ในวิธีอื่นด้วยเช่นกัน!
Bruno Bieri

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รับ byte เดียว ( -n 1) จาก/dev/urandomในช่วง 0-255 ( 00เพื่อFF)
  • เครื่องหมายคำพูดเดี่ยวในอาร์กิวเมนต์สุดท้ายprintfของลูปทำให้ตัวอักขระเป็นเอาต์พุตเป็นค่าตัวเลข ("A" คือเอาต์พุตเป็น "65") ดูข้อกำหนด POSIX สำหรับprintfที่ระบุว่า:

    ถ้าอักขระนำหน้าเป็นเครื่องหมายคำพูดเดี่ยวหรือเครื่องหมายคำพูดคู่ค่าจะเป็นค่าตัวเลขในชุดโค้ดพื้นฐานของอักขระตามเครื่องหมายคำพูดเดี่ยวหรือเครื่องหมายคำพูดคู่


ดูเหมือนว่าจะต้องIFS= read …หลีกเลี่ยงการพับ 09 0a และ 20 (ตัวอักษร IFS ปกติ) เป็น 00
Chris Johnsen

@ Chris: -d ''ขออภัยผมเอาสองสิ่งที่ออกมาจากการตรวจสอบในขณะที่ทำคู่บางและลืมที่จะนำพวกเขากลับมาอยู่ในนอกจากนี้ยังมีความต้องการ. ฉันจะแก้ไขคำตอบของฉัน ขอบคุณสำหรับการให้ฉันรู้ว่า.
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

โอ๊ะโอ-rที่ปกป้อง `` หลุดออกมา ฉันต้องการการจัดการข้อมูลไบนารีที่เหมาะสมในโปรแกรมเชลล์ไม่ได้เล่นแร่แปรธาตุ ☺ดูเหมือนเป็นไปไม่ได้ที่จะเป็นตัวแทนอย่างถูกต้อง 00 ในช่วงกลางของสตริง คุณตัวเดียว-at-เวลาวิธีการจับ 00 โดยอาศัยอำนาจตามความสะดวก (ออกแบบ?) ความร่วมมือระหว่างreadสายการแก้ไขและวิธีการปฏิบัติอาร์กิวเมนต์หนึ่งตัวอักษรprintf 'ถอนหายใจ
Chris Johnsen

@Chris: ฉันหวังว่าโปรเซสเซอร์ DWIM ของฉันไม่ได้อยู่ในฟริตซ์ โดยวิธีการที่คุณอาจจะสนใจที่จะเห็นบริสุทธิ์ทุบตีสคริปต์hexdump -Cที่ผมเขียนว่าซ้ำกันฟังก์ชั่นหลักของ
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

+1 เพิ่มเติมหากคุณสามารถอธิบายสิ่งที่เกิดขึ้นและสาเหตุที่โซลูชันของคุณทำงาน
Jed Daniels

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เคอร์เนล pseudo-สุ่มหมายเลขเคอร์เนลของ 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
end=$( echo $RANDOM | openssl md5 | sed 's/\(..\)/\1-/g' | cut -b-8 )
echo 00-60-2f-$end

5
+1 เพิ่มเติมหากคุณสามารถอธิบายสิ่งที่เกิดขึ้นและสาเหตุที่โซลูชันของคุณใช้งานได้
Jed Daniels

0

อันนี้ใช้ได้ดีเช่นกัน เอาต์พุตจะเป็นตัวพิมพ์ใหญ่ทั้งหมดตามต้องการ

openssl rand -hex 3 | sed 's/\(..\)\(..\)\(..\)/00-60-2F-\1-\2-\3/' | tr [a-f] [A-F]

0

สิ่งนี้ทำงานใน#!/bin/shสคริปต์classic 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'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

1
ระวังด้วยนิดหน่อย ฉันมี mac สร้างวิธีนี้ที่มี "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
nisetama

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.