So generieren Sie eine gültige zufällige MAC-Adresse mit der Bash-Shell


16

Wie kann ich mit bash eine gültige zufällige MAC-Adresse generieren?

Die erste Hälfte der Adresse sollte immer so bleiben

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

soll nur der x wert zufällig generiert werden?


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 Das war schön ... Warum hast du das nicht als Antwort gepostet?
Bobmagoo

Antworten:


18

Hier ist ein Fisch.

Dieses Shell-Skript generiert die zufällige Zeichenfolge, die Sie suchen:

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

Ich hatte hier nur etwas, das zeigte, wie man es von der Kommandozeile aus ausführt, aber nach einem Blick auf Dennis Williamsons komplizierte (aber hochgeladene) Lösung sehe ich, dass die Antwort, die die Leute erwarten, die ist, bei der sie keine Arbeit erledigen müssen sich.


danke, dass ich
gemerkt habe

1
Sie können Ihre Antwort jederzeit erklären, damit Sie ihm beibringen, wie man fischt, und diesmal auch eine ...
Jed Daniels

Dieses Skript läuft erheblich viel schneller als die von hbdgaf vorgeschlagen und erzeugt keine ungültige MAC - Adresse in einer 1000 - mal Schleife. Vielen Dank!
Bruno Finger

1
Ihre Lösung funktioniert und hat nur 3 Zeilen. Ich bin verkauft.
Richard Gomes

17
  1. Generieren Sie ein entsprechend großes int wie folgt : http://tldp.org/LDP/abs/html/randomvar.html
  2. So konvertieren Sie in Hex: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Fügen Sie die Striche zwischen drei zufällig generierten Stücken hinzu
#!/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

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

Beachten Sie, dass die Python-Version nur ein 16-faches Feld zum Generieren eines Hex-Zeichens verwendet, sodass Sie sich keine Gedanken über das Null-Auffüllen machen müssen - Ansatz geändert, um einen Kommentar zu adressieren.


Extra +1, wenn Sie ein Beispiel für jedes Modell angeben (ich weiß, dass Sie ihm das Fischen beibringen, aber Sie können ihm die Puzzleteile zum Zusammenstellen geben und erklären, wie / warum sie funktionieren).
Jed Daniels

@Jed Daniels - fertig und fertig. Code zur Verfügung gestellt.
RobotHumans

Dieser Code generiert ein paar ungültige MACs für mich. Looping es 1000 Mal bekam ich ein paar MACs wie 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Bruno Finger

Es war nur etwas, was ich da rausgeworfen habe, da die OP auf Bash bestand. Sie sagen, Sie können nicht herausfinden, wie die einzelnen Ziffern mit einer Null richtig aufgefüllt werden? @BrunoFinger
RobotHumans

Könnte leicht überarbeitet werden, um 16 anstelle von 255 zu verwenden und den Nullplatzhalter zu erzeugen. Es sind nur mehr Zeilen ...
RobotHumans

16

In der Vergangenheit habe ich folgendes getan:

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

aber das wird sie nur im Bereich von 0-9 machen. Für meine Zwecke war das gut genug.

Eine wahrscheinlich bessere Lösung wäre die Verwendung von printf:

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

So funktioniert das:

  • Das printf-Programm basiert auf der C-Funktion "printf", die als ersten Parameter eine "Formatzeichenfolge" verwendet und dann zusätzliche Parameter in die Formatzeichenfolge einfügt.
  • % in der Formatzeichenfolge führt einen "Formatbezeichner" ein, der ein oder mehrere Zeichen sein kann, die angeben, wie die Argumente formatiert werden sollen.
  • Eine führende Null (0) in einem Formatbezeichner bedeutet, dass die resultierende numerische Ausgabe mit führenden Nullen bis zur angegebenen Breite aufgefüllt werden sollte.
  • Die 2 gibt an, dass der Bezeichner mit zwei Zeichen Breite angezeigt werden soll.
  • Das X beendet den Bezeichner und gibt an, dass er als Zahl interpretiert und als Hexadezimalzahl angezeigt werden soll. Da es sich um Großbuchstaben handelt, sollten die Buchstaben af ​​in Großbuchstaben geschrieben werden.
  • \ N ist eine Newline - printf interpretiert Backslash als Escape-Code, mit dem andere Zeichen angezeigt werden können, häufig schwierige Zeichen wie die Newline.
  • Die verbleibenden Zeichen im Formatbezeichner werden wörtlich ausgedruckt, einschließlich des Anfangsbuchstaben "00-06-2F-" und der Bindestriche zwischen den Formatbezeichnern.
  • Die übrigen Argumente sind Shell-Variablensubstitutionen (mit $ bezeichnet) und enthalten einen mathematischen Ausdruck, der eine Zufallszahl (RANDOM) modulo 256 ist. Dies führt zu einer Zufallszahl zwischen 0 und 255.

2
Wie user58033 in einer Antwort (die jetzt weg sein könnte) zu Recht betonte: %02Xwürde einen Großbuchstaben geben.
Arjan

Ah, guter Punkt. Ich räumte ein, dass die ursprüngliche Frage ein Beispiel mit Großbuchstaben gab. Danke für die Begrüßung. :-)
Sean Reifschneider

Extra +1, wenn Sie erklären können, was gerade passiert und warum Ihre Lösung funktioniert.
Jed Daniels

Los geht's, @Jed.
Sean Reifschneider

12

Auch mit Standardwerkzeugen

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

oder

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

könnte die kürzeste von allen sein.


Können Sie in Ihrer Antwort beschreiben, was od genau tut? Es würde helfen, es auch auf andere Weise zu verwenden!
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"

Die Schlüssel zur Funktionsweise:

  • LC_CTYPE=C - erlaubt Zeichen> 0x7F
  • IFS=- Deaktiviert die Interpretation von \t(Tab), \n(Newline) und Leerzeichen
  • -d ''- erlaubt Zeilenumbrüche
  • -rerlaubt \(und sollte fast immer aus Gewohnheit verwendet werden read)
  • Der Formatbezeichner -%02x\n bewirkt, dass die Ausgabe ein literaler Bindestrich gefolgt von einer zweistelligen Hexadezimalzahl und gegebenenfalls einer führenden Null ist. Die Newline ist hier überflüssig und könnte weggelassen werden.
  • Sie erhalten readein einzelnes Byte ( -n 1) /dev/urandomim Bereich von 0 bis 255 ( 00bis FF).
  • Das einfache Anführungszeichen im letzten Argument printfder Schleife bewirkt, dass das Zeichen als numerischer Wert ausgegeben wird ("A" wird als "65" ausgegeben). In der POSIX-Spezifikationprintf steht:

    Wenn das führende Zeichen ein einfaches Anführungszeichen oder ein doppeltes Anführungszeichen ist, ist der Wert der numerische Wert im zugrunde liegenden Codesatz des Zeichens nach dem einfachen Anführungszeichen oder dem doppelten Anführungszeichen.


Es scheint zu IFS= read …vermeiden, 09 0a und 20 (die üblichen IFS-Zeichen) in 00 zu folden.
Chris Johnsen

@ Chris: Tut mir leid, ich habe ein paar Dinge herausgenommen, während ich sie noch einmal überprüft habe, und habe vergessen, sie wieder einzulegen. Das muss auch sein -d ''. Ich werde meine Antwort reparieren. Danke für die Information.
Bis auf weiteres angehalten.

Ups, das -r, was "\" schützt, ist rausgefallen. Ich wünschte, der richtige Umgang mit Binärdaten in Shell-Programmen wäre nicht so kompliziert. ☺ Es scheint unmöglich zu sein, 00 in der Mitte der Zeichenfolge genau darzustellen. Ihre Einzelzeichenmethode verarbeitet 00 aufgrund der praktischen (entworfenen?) Zusammenarbeit zwischen der readZeichenfolgeninterpolation und der printfBehandlung des Ein-Zeichen-Arguments '. Seufzer.
Chris Johnsen

@ Chris: Ich wünschte, mein DWIM-Prozessor wäre nicht am fritz. Übrigens könnte es Sie interessieren, ein reines Bash-Skript zu sehen , das die Kernfunktionalität von dupliziert hexdump -C.
Bis auf weiteres angehalten.

Extra +1, wenn Sie erklären können, was gerade passiert und warum Ihre Lösung funktioniert.
Jed Daniels

7

Der kürzeste Weg, den ich finden konnte, war die direkte Verwendung von Hexdump

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3 weist hexdump an, drei Bytes zu lesen
  • Die Formatzeichenfolge gibt für jedes Byte einen Bindestrich und einen zweistelligen Hexadezimalwert aus
    • '/ 1' bedeutet, dass für jedes gelesene Byte ein Format angewendet wird
    • "-% 02X" ist eine printf-Spezifikation zum Drucken eines zweistelligen Hex-Werts mit führender Null in Großbuchstaben
  • / dev / random ist ein zufälliges Quellbyte

Getestet unter GNU / Linux


Unix-Effektivität bei der Arbeit :-)
artistoex

hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/randomist etwas kürzer :-)
artistoex

4

Eine andere einzeilige Lösung

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

Gleiches in Großbuchstaben

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

Generieren Sie es für eine Bash-Umgebungsvariable

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

Einzelheiten:

  • od (Oktaldump)

    -AnUnterdrückt die führende Adressendarstellung (zusätzliches Rauschen) der Ausgabe.
    -N3Begrenzen Sie die Ausgabe auf drei Bytes.
    -t xCAusgabe wahlweise in hexadezimaler ASCII-Schreibweise.
    /dev/urandomLinux-Kernel-Zufallszahlen-Pseudodatei.

  • sed (Stream-Editor) Für Leerzeichen zum Ersetzen von Bindestrichen.

    -e <SCRIPT> Führen Sie das sed-Skript aus.

  • tr (Stringübersetzung) Optional in diesem Beispiel. Ich mag MAC-Adressen in Großbuchstaben in meinen Skripten / meiner Umgebung.


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

Das sollte funktionieren

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
Extra +1, wenn Sie erklären können, was gerade passiert und warum Ihre Lösung funktioniert.
Jed Daniels

0

Dieser funktioniert auch. Die Ausgabe erfolgt nach Bedarf in Großbuchstaben.

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

0

Dies funktioniert im klassischen shell ( #!/bin/sh) Skript:

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

Oder, wenn Sie ein benutzerdefiniertes Präfix haben möchten:

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
}

Anwendungsbeispiel:

$ 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

Eine andere Option ist die Verwendung von jot:

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

-wändert das Format, -sändert das Trennzeichen und-r generiert Zufallszahlen.

Die Befehle, die odin den von artistoex und zero2cx geposteten Antworten verwendet werden, fügen der Ausgabe unter OS X zusätzliche Gedankenstriche hinzu od, was jedoch nicht der Fall ist:

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

OS X od( /usr/bin/odunten) verwendet ein anderes Ausgabeformat als 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
Vorsicht mit Jot. Ich habe einen Mac auf diese Weise generiert, der "100" enthält, z. B. 00-60-2F-100-A3-F6 ...
Petrus

@petrus Du hast Recht, herausgegeben ich die Antwort auf Änderung jot -w%02X -s- -r 3 1 256zu jot -w%02X -s- -r 3 0 256.
Nisetama

0

In Linux:

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

Erläuterung:

Unter Linux wird bei jedem Lesen /proc/sys/kernel/random/uuideine neue UUID vom Typ 4 (zufällig) zurückgegeben . Die meisten seiner Zeichen sind (pseudo) zufällige hexadezimale Ziffern, daher können wir sie verwenden. Z.B:

$ 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

Jetzt genügt es, zuerst 00-60-2f-(ohne Zeilenvorschub) zu drucken :

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

Vorteile:

  • Hexadezimalziffern von Anfang an, keine Konvertierung / Filterung erforderlich;
  • printf und cut sind POSIX-Tools;
  • (für Ihren speziellen Fall) Bindestriche, die bereits in UUID enthalten sind, verwenden wir.

Nachteile:

  • Wir müssen die beiden nicht zufälligen Ziffern in der UUID beachten.
  • /proc/sys/kernel/random/uuid ist auf einigen Systemen möglicherweise nicht verfügbar;
  • Nur Kleinbuchstaben sind so einfach (Sie benötigen einen zusätzlichen Schritt, um Großbuchstaben zu erhalten).

0

Ein Liner (Bash)

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

Ergebnis

$ echo $mac
93:72:71:0B:9E:89
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.