Cách tạo Địa chỉ MAC ngẫu nhiên hợp lệ với bash shell


16

Làm thế nào tôi có thể tạo ra một địa chỉ mac ngẫu nhiên hợp lệ với bash.

Nửa đầu của địa chỉ phải luôn như thế này

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

chỉ nên tạo giá trị 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 Thật là đẹp ... Tại sao bạn không đăng nó như là câu trả lời?
bobmagoo

Câu trả lời:


18

Đây là một con cá.

Kịch bản shell này sẽ tạo ra chuỗi ngẫu nhiên bạn tìm kiếm:

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

Tôi đã có một cái gì đó ở đây chỉ ra cách chạy nó từ dòng lệnh, nhưng sau khi xem giải pháp Dennis Williamson bị xáo trộn (nhưng được nâng cấp), tôi thấy rằng câu trả lời mà mọi người mong đợi là câu trả lời mà họ không phải làm chúng tôi.


cảm ơn vì nhận ra rằng tôi đã cố gắng để làm cho anh ta học cách câu cá thay vì muỗng-ăn một giải pháp
RobotHumans

1
Bạn luôn có thể giải thích câu trả lời của mình để cả hai cùng dạy anh ấy cách câu cá ngoài việc cung cấp một lần trong khoảng thời gian này ...
Jed Daniels

Kịch bản này chạy khá nhiều nhanh hơn so với từng người hbdgaf đề xuất và không tạo ra bất kỳ địa chỉ MAC không hợp lệ trong một lần lặp 1000. Cảm ơn!
Bruno Finger

1
Giải pháp của bạn hoạt động và chỉ có 3 dòng. Tôi đang bán.
Richard Gomes

17
  1. Tạo một int có kích thước phù hợp như vậy: http://tldp.org/LDP/abs/html/randomvar.html
  2. Chuyển đổi sang hex như vậy: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Thêm dấu gạch ngang giữa ba khối được tạo ngẫu nhiên
#!/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

Hoặc trong trăn:

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

Lưu ý rằng phiên bản python chỉ sử dụng trường rộng 16 để tạo char hex, vì vậy bạn không phải lo lắng về phần đệm bằng không - cách tiếp cận được sửa đổi để giải quyết một nhận xét.


Thêm +1 nếu bạn cung cấp một ví dụ về mỗi câu (Tôi biết bạn đang dạy anh ấy cách câu cá, nhưng bạn có thể đưa cho anh ấy những mảnh ghép để ghép lại và giải thích cách thức / lý do chúng hoạt động).
Jed Daniels

@Jed Daniels - thực hiện và thực hiện. mã được cung cấp.
RobotHumans

Mã này đang tạo ra một vài MAC không hợp lệ cho tôi. Looping nó 1000 lần tôi có một vài máy Mac như 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Bruno Finger

Đó chỉ là thứ tôi đã ném ra ngoài vì OP đã khăng khăng đòi bash. Bạn đang nói rằng bạn không thể tìm ra cách đệm các chữ số đơn bằng 0 phải không? @BrunoFinger
RobotHumans 22/03/2015

Có thể dễ dàng làm lại để sử dụng 16 thay vì 255 và tạo giữ chỗ bằng không. Nó chỉ là nhiều dòng hơn ...
RobotHumans 22/03/2015

16

Trước đây tôi đã làm điều này bằng cách sử dụng:

echo 00-60-2F-$[RANDOM%10]$[RANDOM%10]-$[RANDOM%10]$[RANDOM%10]-$[RANDOM%10]$[RANDOM%10]

nhưng điều đó sẽ chỉ làm cho chúng trong phạm vi 0-9. Đối với mục đích của tôi, điều đó là đủ tốt.

Có lẽ một giải pháp tốt hơn sẽ là sử dụng printf:

printf '00-60-2F-%02X-%02X-%02X\n' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256]

Đây là cách nó hoạt động:

  • Chương trình printf dựa trên hàm C "printf", lấy "chuỗi định dạng" làm tham số đầu tiên và sau đó tham số bổ sung điền vào chuỗi định dạng.
  • % trong chuỗi định dạng giới thiệu một "trình xác định định dạng" có thể là một hoặc nhiều ký tự cho biết cách định dạng các đối số.
  • Số 0 (0) hàng đầu trong một công cụ xác định định dạng có nghĩa là đầu ra số kết quả phải được đệm với các số 0 đứng đầu đến chiều rộng đã chỉ định.
  • 2 nói rằng specifier nên được hiển thị chiếm hai chiều rộng.
  • X kết thúc bộ xác định và biểu thị rằng nó nên được hiểu là một số và được hiển thị dưới dạng thập lục phân. Bởi vì nó là chữ hoa, các chữ cái af nên viết hoa.
  • \ N là một dòng mới - printf diễn giải dấu gạch chéo ngược dưới dạng mã thoát có thể được sử dụng để hiển thị các ký tự khác, thường là các ký tự khó như dòng mới.
  • Các ký tự còn lại trong trình xác định định dạng được in ra theo nghĩa đen, bao gồm "00-06-2F-" ban đầu và dấu gạch ngang giữa các chỉ định định dạng.
  • Các đối số còn lại là các thay thế biến vỏ (được ký hiệu là $) và bao gồm một biểu thức toán học là một số ngẫu nhiên (RANDOM) modulo 256. Điều này dẫn đến một số ngẫu nhiên trong khoảng từ 0 đến 255.

2
Như user58033 đã chỉ ra một cách chính xác trong một câu trả lời (có thể không còn nữa): %02Xsẽ đưa ra một chữ cái viết hoa.
Arjan

Ah, điểm tốt. Tôi cách nhau rằng câu hỏi ban đầu đã đưa ra một ví dụ sử dụng chữ hoa. Cảm ơn đã chào đón. :-)
Sean Reifschneider

Thêm +1 nếu bạn có thể giải thích những gì đang xảy ra và tại sao giải pháp của bạn hoạt động.
Jed Daniels

Có bạn đi, @Jed.
Sean Reifschneider

12

Sử dụng các công cụ tiêu chuẩn, hoặc

# output in capitals
hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/random

hoặc là

# output in lower case letters
echo 00-60-2f$(od -txC -An -N3 /dev/random|tr \  -)

có thể là ngắn nhất trong tất cả.


Bạn có thể mô tả trong câu trả lời của bạn chính xác những gì od? Nó cũng sẽ giúp sử dụng nó theo những cách khác!
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"

Các chìa khóa để làm việc này:

  • LC_CTYPE=C - cho phép các ký tự> 0x7F
  • IFS=- vô hiệu hóa giải thích \t(tab), \n(dòng mới) và dấu cách
  • -d ''- cho phép dòng mới
  • -rcho phép \(và hầu như luôn luôn được sử dụng theo thói quen vớiread )
  • Định dạng định dạng -%02x\n làm cho đầu ra là một dấu gạch ngang theo sau bằng số thập lục phân hai chữ số bao gồm số 0 đứng đầu, nếu phù hợp. Dòng mới là không cần thiết ở đây và có thể được bỏ qua.
  • Nhận readđược một byte ( -n 1) từ /dev/urandomtrong phạm vi 0 đến 255 ( 00đến FF).
  • Dấu ngoặc đơn trong đối số cuối cùng printftrong vòng lặp làm cho ký tự được xuất thành giá trị số của nó ("A" là đầu ra là "65"). Xem thông số kỹ thuật POSIX để biếtprintf nơi nó nói:

    Nếu ký tự đầu là một trích dẫn đơn hoặc trích dẫn kép, giá trị sẽ là giá trị số trong bộ mã cơ bản của ký tự theo sau trích dẫn đơn hoặc trích dẫn kép.


Dường như cần IFS= read …tránh gấp 09 0a và 20 (ký tự IFS thông thường) thành 00.
Chris Johnsen

@Chris: Xin lỗi, tôi đã lấy một vài thứ ra trong khi thực hiện một số kiểm tra kép và quên không đặt chúng trở lại. Nó cũng cần -d ''. Tôi sẽ sửa câu trả lời của tôi. Cảm ơn vì đã cho tôi biết.
Tạm dừng cho đến khi có thông báo mới.

Rất tiếc, -rbảo vệ `\` rơi ra. Tôi muốn xử lý thích hợp dữ liệu nhị phân trong các chương trình shell không quá khó. Dường như không thể biểu diễn chính xác 00 ở giữa chuỗi. Phương thức một ký tự một lần của bạn xử lý 00 nhờ sự hợp tác thuận tiện (được thiết kế?) Giữa read, nội suy chuỗi và cách printfxử lý đối số một ký tự '. Thở dài.
Chris Johnsen

@Chris: Tôi muốn bộ xử lý DWIM của tôi không chạy trên fritz. Nhân tiện, bạn có thể thích thú khi thấy một tập lệnh Bash thuần túy mà tôi đã viết trùng lặp chức năng cốt lõi của hexdump -C.
Tạm dừng cho đến khi có thông báo mới.

Thêm +1 nếu bạn có thể giải thích những gì đang xảy ra và tại sao giải pháp của bạn hoạt động.
Jed Daniels

7

Cách ngắn nhất tôi có thể nghĩ ra là sử dụng hexdump trực tiếp

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3 bảo hexdump đọc ba ô.
  • Chuỗi định dạng in một dấu gạch ngang và giá trị hex hai chữ số cho mỗi byte
    • '/ 1' có nghĩa là định dạng áp dụng cho mỗi byte đọc
    • "-% 02X" là thông số printf để in giá trị hex hàng đầu, hai chữ số, chữ hoa
  • / dev / Random là một byte ngẫu nhiên nguồn

Đã thử nghiệm trên GNU / Linux


Hiệu quả của Unix trong công việc :-)
artistoex

hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/randomngắn hơn một chút :-)
artistoex

4

Một giải pháp một dòng khác

$ echo '00 60 2f'$(od -An -N3 -t xC /dev/urandom) | sed -e 's/ /-/g'

Điều tương tự trong chữ hoa

$ echo '00 60 2f'$(od -An -N3 -t xC /dev/urandom) | sed -e 's/ /-/g' | tr '[:lower:]' '[:upper:]'

Tạo nó cho biến môi trường Bash

$ export MAC=$(echo '00 60 2f'$(od -An -N3 -t xC /dev/urandom) | sed -e 's/ /-/g')
$ echo $MAC

Chi tiết:

  • od (bãi bát phân)

    -AnLoại bỏ đại diện địa chỉ hàng đầu (thêm nhiễu) của đầu ra.
    -N3Giới hạn đầu ra đến ba byte.
    -t xCĐầu ra ở dạng hex, ký tự ASCII, như mong muốn.
    /dev/urandomLinux kernel số giả ngẫu nhiên tập tin.

  • sed (trình chỉnh sửa luồng) Dành cho không gian để thay thế dấu gạch nối.

    -e <SCRIPT> thực hiện kịch bản sed.

  • tr (dịch chuỗi) Tùy chọn, trong ví dụ này. Tôi thích địa chỉ MAC chữ hoa trong tập lệnh / môi trường của tôi.


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

Điều này sẽ làm việc

echo 00-60-2f-`openssl rand -hex 3 | sed 's/\(..\)/\1-/g; s/.$//'`

0
end=$( echo $RANDOM | openssl md5 | sed 's/\(..\)/\1-/g' | cut -b-8 )
echo 00-60-2f-$end

5
Thêm +1 nếu bạn có thể giải thích những gì đang xảy ra và tại sao giải pháp của bạn hoạt động.
Jed Daniels

0

Điều này làm việc là tốt. Đầu ra là tất cả trong trường hợp trên theo yêu cầu.

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

0

Đây là tác phẩm trong #!/bin/shtập lệnh shell ( ) cổ điển :

random_mac() {
    printf '%.2x\n' "$(shuf -i 0-281474976710655 -n 1)" | sed -r 's/(..)/\1:/g' | cut -d: -f -6
}

Hoặc, nếu bạn muốn có tiền tố tùy chỉnh:

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
}

Ví dụ sử dụng:

$ 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

Một lựa chọn khác là sử dụng jot:

echo 00-60-2F-$(jot -w%02X -s- -r 3 0 256)

-wthay đổi định dạng, -sthay đổi dấu phân cách và -rtạo số ngẫu nhiên.

Các lệnh sử dụng odtrong các câu trả lời được đăng bởi artistoex và zero2cx sẽ thêm dấu gạch ngang vào đầu ra với OS X od, nhưng điều này không:

echo 00-60-2f-$(od -tx1 -An -N3 /dev/random|awk '$1=$1'|tr \  -)

OS X's od( /usr/bin/odbên dưới) sử dụng định dạng đầu ra khác với 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
Cẩn thận với jot. Tôi có một số mac được tạo theo cách này có "100" trong đó, ví dụ 00-60-2F-100-A3-F6 ...
petrus

@petrus Bạn nói đúng, tôi thay đổi nội dung câu trả lời cho sự thay đổi jot -w%02X -s- -r 3 1 256để jot -w%02X -s- -r 3 0 256.
nisetama

0

Trong Linux:

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

Giải trình:

Trong Linux /proc/sys/kernel/random/uuidtrả về UUID loại 4 (ngẫu nhiên) mới mỗi khi bạn đọc nó. Hầu hết các ký tự của nó là các chữ số thập lục phân ngẫu nhiên (giả), do đó chúng ta có thể sử dụng chúng. Ví dụ:

$ 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

Bây giờ đã đủ để in 00-60-2f-(không có dòng mới) trước:

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

Ưu điểm:

  • chữ số thập lục phân ngay từ đầu, không cần chuyển đổi / lọc;
  • printfcutlà các công cụ POSIX;
  • (đối với trường hợp cụ thể của bạn) các dấu gạch nối đã có trong UUID, chúng tôi sử dụng chúng.

Nhược điểm:

  • chúng ta cần lưu ý hai chữ số không ngẫu nhiên trong UUID;
  • /proc/sys/kernel/random/uuid có thể không có sẵn trên một số hệ thống;
  • chỉ có chữ cái viết thường đến dễ dàng (bạn cần thêm bước để có được chữ cái viết hoa).

0

Một lớp lót (bash)

mac=$(c=0;until [ $c -eq "6" ];do printf ":%02X" $(( $RANDOM % 256 ));let c=c+1;done|sed s/://)

kết quả

$ echo $mac
93:72:71:0B:9E:89
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.