Cara menghasilkan Alamat MAC acak yang valid dengan bash shell

16

Bagaimana saya bisa menghasilkan alamat mac acak yang valid dengan bash.

Paruh pertama dari alamat harus selalu tetap sama seperti ini

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

hanya nilai x yang harus dihasilkan secara acak?

NES
sumber
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 Itu indah ... Mengapa Anda tidak memposting itu sebagai jawabannya?
bobmagoo

Jawaban:

18

Ini ikan.

Script shell ini akan menghasilkan string acak yang Anda cari:

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

Saya memang punya sesuatu di sini yang menunjukkan cara menjalankannya dari baris perintah, tetapi setelah melihat Dennis Williamson solusi yang berbelit-belit (tapi tervotasikan) saya melihat bahwa jawaban yang orang harapkan adalah jawaban di mana mereka tidak perlu melakukan pekerjaan apa pun diri.

deltaray
sumber
terima kasih karena menyadari bahwa saya mencoba membuatnya belajar memancing bukannya mencari makan dengan sendok
RobotHumans
1
Anda selalu bisa menjelaskan jawaban Anda sehingga Anda berdua mengajarinya cara memancing dan juga menyediakan satu kali ini ...
Jed Daniels
Script ini berjalan jauh lebih cepat daripada yang diusulkan oleh hbdgaf dan tidak menghasilkan alamat MAC yang tidak valid dalam 1000 kali loop. Terima kasih!
Bruno Finger
1
Solusi Anda berfungsi dan hanya memiliki 3 baris. Aku terjual.
Richard Gomes
17

Di masa lalu saya telah melakukan ini menggunakan:

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

tapi itu hanya akan membuat mereka berada di kisaran 0-9. Demi tujuan saya, itu sudah cukup baik.

Mungkin solusi yang lebih baik adalah menggunakan printf:

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

Begini cara kerjanya:

  • Program printf didasarkan pada fungsi C "printf", yang mengambil "format string" sebagai parameter pertama dan kemudian parameter tambahan mengisi string format.
  • % dalam format string memperkenalkan "format specifier" yang dapat berupa satu atau lebih karakter yang memberi tahu cara memformat argumen.
  • Nol awal (0) dalam penentu format berarti bahwa output numerik yang dihasilkan harus diisi dengan nol di depan hingga lebar yang ditentukan.
  • Angka 2 mengatakan bahwa specifier harus ditampilkan dengan lebar dua karakter.
  • X mengakhiri specifier dan menunjukkan bahwa itu harus ditafsirkan sebagai angka dan ditampilkan sebagai hexidecimal. Karena huruf besar, huruf af harus huruf besar.
  • \ N adalah baris baru - printf menginterpretasikan garis miring terbalik sebagai kode pelarian yang dapat digunakan untuk menampilkan karakter lain, seringkali karakter yang rumit seperti baris baru.
  • Karakter yang tersisa dalam penentu format dicetak secara harfiah, ini termasuk awal "00-06-2F-" dan tanda hubung antara penentu format.
  • Argumen yang tersisa adalah substitusi variabel shell (dilambangkan dengan $) dan termasuk ekspresi matematika yang merupakan nomor acak (RANDOM) modulo 256. Ini menghasilkan angka acak antara 0 dan 255.
Sean Reifschneider
sumber
2
Seperti yang ditunjukkan oleh user58033 dalam jawaban (yang mungkin hilang sekarang): %02Xakan memberikan satu huruf besar.
Arjan
Ah, poin bagus. Saya memberi spasi bahwa pertanyaan awal memberi contoh menggunakan huruf besar. Terima kasih atas sambutannya. :-)
Sean Reifschneider
Ekstra +1 jika Anda dapat menjelaskan apa yang terjadi dan mengapa solusi Anda berfungsi.
Jed Daniels
Ini dia, @Jed.
Sean Reifschneider
17
  1. Buat int berukuran tepat seperti: http://tldp.org/LDP/abs/html/randomvar.html
  2. Konversikan ke hex seperti: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Tambahkan tanda hubung di antara tiga potongan yang dibuat secara acak
#!/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

Atau dengan python:

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

Perhatikan bahwa versi python hanya menggunakan bidang 16 lebar untuk menghasilkan hex char, jadi Anda tidak perlu khawatir tentang nol padding - pendekatan diubah untuk mengatasi komentar.

RobotHumans
sumber
Ekstra +1 jika Anda memberikan contoh masing-masing (saya tahu Anda mengajarinya cara memancing, tetapi Anda bisa memberinya potongan-potongan teka-teki untuk disatukan, dan menjelaskan bagaimana / mengapa mereka bekerja).
Jed Daniels
@Jed Daniels - selesai dan dilakukan. kode disediakan.
RobotHumans
Kode ini menghasilkan beberapa MAC yang tidak valid untuk saya. Perulangan itu 1000 kali aku punya beberapa Mac seperti 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Bruno Finger
Itu hanya sesuatu yang saya buang di sana karena OP bersikeras bash. Anda mengatakan Anda tidak tahu bagaimana cara memasukkan satu digit angka dengan angka nol, bukan? @BrunoFinger
RobotHumans
Bisa dengan mudah dikerjakan ulang menggunakan 16 bukannya 255 dan menghasilkan tempat penampung nol. Itu hanya lebih banyak baris ...
RobotHumans
12

Menggunakan alat standar, baik

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

atau

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

mungkin yang terpendek dari semuanya.

artisoex
sumber
Bisakah Anda jelaskan dalam jawaban Anda apa yang sebenarnya dilakukan? Ini akan membantu menggunakannya dengan cara lain juga!
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"

Kunci cara kerjanya:

  • LC_CTYPE=C - memungkinkan karakter> 0x7F
  • IFS=- Menonaktifkan interpretasi \t(tab), \n(baris baru) dan ruang
  • -d ''- memungkinkan baris baru
  • -rmemungkinkan \(dan harus hampir selalu digunakan oleh kebiasaan dengan read)
  • Penentu format -%02x\nmenyebabkan output menjadi tanda hubung literal diikuti oleh bilangan heksadesimal dua digit termasuk nol di depan, jika perlu. Baris baru berlebihan di sini dan bisa dihilangkan.
  • The readmendapat satu byte ( -n 1) dari /dev/urandomdalam kisaran 0 sampai 255 ( 00untuk FF).
  • Kutipan tunggal dalam argumen terakhir ke printfdalam loop menyebabkan karakter menjadi output sebagai nilai numeriknya ("A" adalah output sebagai "65"). Lihat spesifikasi POSIX untukprintf mengatakan:

    Jika karakter utama adalah kuotasi tunggal atau kuotasi ganda, nilainya harus berupa nilai numerik dalam kumpulan kode yang mendasari karakter yang mengikuti kuotasi tunggal atau kuotasi ganda.

Dijeda sampai pemberitahuan lebih lanjut.
sumber
Tampaknya perlu IFS= read …untuk menghindari melipat 09 0a dan 20 (karakter IFS biasa) menjadi 00.
Chris Johnsen
@ Chris: Maaf, saya mengeluarkan beberapa hal sambil melakukan pengecekan ganda dan lupa memasangnya kembali. Itu juga perlu -d ''. Saya akan memperbaiki jawaban saya. Terima kasih telah memberi tahu saya.
Dijeda sampai pemberitahuan lebih lanjut.
Ups, -ryang melindungi `\` rontok. Saya berharap penanganan yang tepat dari data biner dalam program shell tidak terlalu rumit. ☺ Tampaknya mustahil untuk secara akurat mewakili 00 di tengah-tengah string. Metode single-character-at-a-time Anda menangani 00 berdasarkan kerjasama yang nyaman (dirancang?) Antara read, interpolasi string dan bagaimana printfmemperlakukan argumen satu karakter '. Mendesah.
Chris Johnsen
@ Chris: Saya berharap prosesor DWIM saya tidak ada di fritz. Omong-omong, Anda mungkin tertarik untuk melihat skrip Bash murni yang saya tulis yang menduplikasi fungsionalitas inti hexdump -C.
Dijeda sampai pemberitahuan lebih lanjut.
Ekstra +1 jika Anda dapat menjelaskan apa yang terjadi dan mengapa solusi Anda berfungsi.
Jed Daniels
7

Cara terpendek yang bisa saya lakukan adalah menggunakan hexdump secara langsung

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3 memberitahu hexdump untuk membaca tiga byytes
  • String format mencetak tanda hubung dan nilai hex dua digit untuk setiap byte
    • '/ 1' berarti menerapkan format untuk setiap byte baca
    • "-% 02X" adalah spesifikasi printf untuk mencetak nilai hex nol, dua digit, huruf besar
  • / dev / random adalah sumber byte acak

Diuji pada GNU / Linux

maxthoursie
sumber
Unix efektivitas di tempat kerja :-)
artistoex
hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/randomsedikit lebih pendek :-)
artistoex
4

Solusi satu baris lainnya

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

Hal yang sama dalam huruf besar

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

Hasilkan untuk variabel lingkungan Bash

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

Detail:

  • od (dump oktal)

    -AnMenekan representasi alamat utama (noise ekstra) dari output.
    -N3Batasi output hingga tiga byte.
    -t xCKeluaran dalam hex, gaya karakter ASCII, seperti yang diinginkan.
    /dev/urandomLinux pseudo-file kernel angka acak.

  • sed (stream editor) Untuk ruang pengganti tanda hubung.

    -e <SCRIPT> jalankan skrip sed.

  • tr (terjemahan string) Opsional, dalam contoh ini. Saya suka alamat MAC huruf besar di skrip / lingkungan saya.

nol2cx
sumber
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
Hematoma
sumber
2

Ini seharusnya bekerja

echo 00-60-2f-`openssl rand -hex 3 | sed 's/\(..\)/\1-/g; s/.$//'`
linuxrules94
sumber
0
end=$( echo $RANDOM | openssl md5 | sed 's/\(..\)/\1-/g' | cut -b-8 )
echo 00-60-2f-$end
Kevin Duterne
sumber
5
Ekstra +1 jika Anda dapat menjelaskan apa yang terjadi dan mengapa solusi Anda berfungsi.
Jed Daniels
0

Yang ini juga berfungsi. Output semua dalam huruf besar sesuai kebutuhan.

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

Ini berfungsi dalam #!/bin/shskrip shell ( ) klasik :

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

Atau, jika Anda ingin memiliki awalan khusus:

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
}

Contoh penggunaan:

$ 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
sumber
0

Pilihan lain adalah menggunakan jot:

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

-wmengubah format, -smengubah pemisah, dan -rmenghasilkan angka acak.

Perintah yang digunakan oddalam jawaban yang diposting oleh artistoex dan zero2cx menambahkan tanda hubung ekstra ke output dengan OS X's od, tetapi ini tidak:

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

OS X od(di /usr/bin/odbawah) menggunakan format output yang berbeda dari 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
sumber
1
Waspadalah dengan catatan. Saya memiliki beberapa mac yang dihasilkan dengan cara ini yang memiliki "100" di dalamnya, mis. 00-60-2F-100-A3-F6 ...
petrus
@petrus Anda benar, saya mengedit jawaban untuk diubah jot -w%02X -s- -r 3 1 256menjadi jot -w%02X -s- -r 3 0 256.
nisetama
0

Di Linux:

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

Penjelasan:

Di Linux /proc/sys/kernel/random/uuidmengembalikan yang baru UUID tipe 4 baru (acak) setiap kali Anda membacanya. Sebagian besar karakternya adalah (pseudo) angka heksadesimal acak, sehingga kita dapat menggunakannya. Misalnya:

$ 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

Sekarang sudah cukup untuk mencetak 00-60-2f- (tanpa baris baru) terlebih dahulu:

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

Pro:

  • digit heksadesimal dari awal, tidak perlu konversi / filter;
  • printf dan cut merupakan alat POSIX;
  • (untuk kasus spesifik Anda) tanda hubung sudah dalam UUID, kami menggunakannya.

Cons:

  • kita perlu mengingat dua digit non-acak dalam UUID;
  • /proc/sys/kernel/random/uuid mungkin tidak tersedia di beberapa sistem;
  • hanya huruf kecil yang begitu mudah (Anda perlu langkah tambahan untuk mendapatkan huruf besar).
Kamil Maciorowski
sumber
0

One liner (bash)

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

hasil

$ echo $mac
93:72:71:0B:9E:89
Zibri
sumber