Come generare un indirizzo MAC casuale valido con shell bash


16

Come posso generare un indirizzo Mac casuale valido con bash.

La prima metà dell'indirizzo dovrebbe rimanere sempre la stessa

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

solo il valore x dovrebbe essere generato casualmente?


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 È stato bellissimo ... Perché non l'hai pubblicato come risposta?
bobmagoo,

Risposte:


18

Ecco un pesce

Questo script di shell genererà la stringa casuale che cerchi:

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

Avevo solo qualcosa qui che mostrava come eseguirlo dalla riga di comando, ma dopo aver visto la soluzione contorta (ma migliorata) di Dennis Williamson, vedo che la risposta che la gente si aspetta è quella in cui non è necessario svolgere alcun lavoro loro stessi.


grazie per aver realizzato che stavo cercando di fargli imparare a pescare invece di dargli da mangiare una soluzione
RobotHumans,

1
Potresti sempre spiegare la tua risposta in modo che entrambi gli stiate insegnando a pescare oltre a fornirne una volta ...
Jed Daniels,

Questo script viene eseguito molto più velocemente di quello proposto da hbdgaf e non genera alcun indirizzo MAC non valido in un ciclo 1000 volte. Grazie!
Bruno Finger,

1
La tua soluzione funziona e ha solo 3 righe. Sono venduto.
Richard Gomes,

17

In passato l'ho fatto usando:

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

ma questo li renderà solo nell'intervallo 0-9. Per i miei scopi, era abbastanza buono.

Probabilmente una soluzione migliore sarebbe usare printf:

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

Ecco come funziona:

  • Il programma printf si basa sulla funzione C "printf", che accetta una "stringa di formato" come primo parametro e quindi i parametri aggiuntivi riempiono la stringa di formato.
  • % nella stringa di formato introduce un "identificatore di formato" che può essere uno o più caratteri che indicano come formattare gli argomenti.
  • Uno zero iniziale (0) in un identificatore di formato significa che l'output numerico risultante deve essere riempito con zeri iniziali fino alla larghezza specificata.
  • Il 2 dice che l'identificatore dovrebbe essere visualizzato occupando due caratteri di larghezza.
  • La X termina lo specificatore e indica che dovrebbe essere interpretato come un numero e visualizzato come esadecimale. Poiché è in maiuscolo, le lettere af devono essere in maiuscolo.
  • La \ n è una nuova riga: printf interpreta la barra rovesciata come un codice di escape che può essere utilizzato per visualizzare altri caratteri, spesso caratteri complicati come la nuova riga.
  • I caratteri rimanenti nell'identificatore di formato vengono stampati letteralmente, questo include "00-06-2F-" iniziale e i trattini tra gli identificatori di formato.
  • Gli argomenti rimanenti sono sostituzioni di variabili shell (indicate da $) e includono un'espressione matematica che è un numero casuale (RANDOM) modulo 256. Il risultato è un numero casuale compreso tra 0 e 255.

2
Come giustamente user58033 ha sottolineato in una risposta (che potrebbe essere sparita ora): %02Xdarebbe una lettera maiuscola.
Arjan,

Ah, buon punto. Ho spaziato sul fatto che la domanda originale forniva un esempio usando le maiuscole. Grazie per il benvenuto :-)
Sean Reifschneider il

Extra +1 se puoi spiegare cosa sta succedendo e perché la tua soluzione funziona.
Jed Daniels,

Ecco qua, @Jed.
Sean Reifschneider,

17
  1. Genera un int di dimensioni adeguate in questo modo: http://tldp.org/LDP/abs/html/randomvar.html
  2. Converti in esadecimale in questo modo: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Aggiungi i trattini tra tre blocchi generati casualmente
#!/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

O in pitone:

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

Nota che la versione di Python utilizza solo un campo largo 16 per generare un carattere esadecimale, quindi non devi preoccuparti di zero padding - approccio modificato per indirizzare un commento.


+1 extra se fornisci un esempio di ciascuno (so che gli stai insegnando a pescare, ma potresti dargli i pezzi del puzzle da mettere insieme e spiegare come / perché funzionano).
Jed Daniels,

@Jed Daniels - fatto e fatto. codice fornito.
RobotHumans,

Questo codice sta generando alcuni MAC non validi per me. Looping è 1000 volte ho avuto un paio di MAC come 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Bruno Finger,

Era solo qualcosa che ho gettato là fuori dal momento che l'OP insisteva per bash. Stai dicendo che non riesci a capire come riempire le singole cifre con uno zero giusto? @BrunoFinger
RobotHumans il

Potrebbe essere facilmente rielaborato per utilizzare 16 anziché 255 e generare il segnaposto zero. Sono solo più righe ...
RobotHumans,

12

Utilizzando anche strumenti standard

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

o

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

potrebbe essere il più breve di tutti.


Puoi descrivere nella tua risposta cosa od fa esattamente? Aiuterebbe ad usarlo anche in altri modi!
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"

Le chiavi del modo in cui funziona:

  • LC_CTYPE=C - consente caratteri> 0x7F
  • IFS=- disabilita l'interpretazione di \t(tab), \n(newline) e spazio
  • -d ''- consente newline
  • -rconsente \(e dovrebbe quasi sempre essere utilizzato per abitudine con read)
  • L'identificatore di formato -%02x\nfa sì che l'output sia un trattino letterale seguito da un numero esadecimale a due cifre incluso uno zero iniziale, se appropriato. La newline è superflua qui e potrebbe essere omessa.
  • Il readottiene un singolo byte ( -n 1) dal /dev/urandomnell'intervallo da 0 a 255 ( 00a FF).
  • La virgoletta singola nell'ultimo argomento printfnel ciclo provoca l'output del carattere come valore numerico ("A" viene emesso come "65"). Vedi le specifiche POSIX perprintf dove dice:

    Se il carattere principale è una virgoletta singola o una virgoletta doppia, il valore deve essere il valore numerico nel set di codici sottostante del carattere che segue la virgoletta singola o la virgoletta doppia.


Sembra che debba IFS= read …evitare di piegare 09 0a e 20 (i soliti caratteri IFS) in 00.
Chris Johnsen,

@ Chris: Mi dispiace, ho preso un paio di cose mentre facevo un doppio controllo e ho dimenticato di rimetterle dentro. Ha anche bisogno -d ''. Riparerò la mia risposta. Grazie per avermi fatto sapere.
In pausa fino a ulteriore avviso.

Oops, quello -rche protegge `` è caduto fuori. Vorrei che la corretta gestione dei dati binari nei programmi shell non fosse così complicata. ☺ Sembra impossibile rappresentare con precisione 00 nel mezzo della stringa. Il tuo metodo a carattere singolo alla volta gestisce 00 in virtù della comoda (progettata?) Cooperazione tra l' readinterpolazione di stringhe e il modo in cui printftratta l'argomento di un carattere '. Sospiro.
Chris Johnsen,

@ Chris: Vorrei che il mio processore DWIM non fosse in crisi. A proposito, potresti essere interessato a vedere un puro script Bash che ho scritto che duplica le funzionalità di base hexdump -C.
In pausa fino a ulteriore avviso.

Extra +1 se puoi spiegare cosa sta succedendo e perché la tua soluzione funziona.
Jed Daniels,

7

Il modo più breve che potevo trovare era usare direttamente hexdump

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3 dice a hexdump di leggere tre byte
  • La stringa di formato stampa un trattino e un valore esadecimale a due cifre per ogni byte
    • '/ 1' significa applicare il formato per ogni byte letto
    • "-% 02X" è una specifica printf per la stampa di un valore esadecimale maiuscolo, a due cifre, iniziale
  • / dev / random è un byte casuale di origine

Testato su GNU / Linux



hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/randomè un po 'più breve :-)
artistoex

4

Un'altra soluzione a una riga

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

Stessa cosa in maiuscolo

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

Generalo per una variabile d'ambiente Bash

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

Dettagli:

  • od (discarica ottale)

    -AnElimina la rappresentazione dell'indirizzo principale (rumore extra) dell'output.
    -N3Limitare l'output a tre byte.
    -t xCUscita in esadecimale, stile di carattere ASCII, come desiderato.
    /dev/urandomPseudo-file con numero casuale del kernel Linux.

  • sed (stream editor) Per lo spazio alla sostituzione del trattino.

    -e <SCRIPT> eseguire lo script sed.

  • tr (traduzione stringa) Facoltativo, in questo esempio. Mi piacciono gli indirizzi MAC maiuscoli nei miei script / ambiente.


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

Questo dovrebbe funzionare

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 se puoi spiegare cosa sta succedendo e perché la tua soluzione funziona.
Jed Daniels,

0

Anche questo funziona. L'output è tutto in maiuscolo come richiesto.

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

0

Funziona con il classico #!/bin/shscript shell ( ):

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

Oppure, se si desidera avere un prefisso personalizzato:

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
}

Esempio di utilizzo:

$ 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

Un'altra opzione è utilizzare jot:

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

-wcambia il formato, -scambia il separatore e-r genera numeri casuali.

I comandi che usano odnelle risposte postate da artistoex e zero2cx aggiungono trattini extra all'output con OS X od, ma questo non:

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

OS X od( /usr/bin/odsotto) utilizza un formato di output diverso da 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
Attenti con jot. Ho generato alcuni mac in questo modo che contengono "100", ad es. 00-60-2F-100-A3-F6 ...
petrus

@petrus Hai ragione, ho modificato la risposta per passare jot -w%02X -s- -r 3 1 256a 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

Spiegazione:

In Linux /proc/sys/kernel/random/uuidrestituisce un nuovo UUID di tipo 4 (casuale) ogni volta che lo leggi. La maggior parte dei suoi personaggi sono cifre esadecimali (pseudo) casuali, quindi possiamo usarle. Per esempio:

$ 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

Ora è sufficiente stampare prima 00-60-2f-(senza riga nuova):

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

Professionisti:

  • cifre esadecimali sin dall'inizio, nessuna conversione / filtro necessari;
  • printfe cutsono strumenti POSIX;
  • (per il tuo caso specifico) trattini già in UUID, li usiamo.

Contro:

  • dobbiamo considerare le due cifre non casuali in UUID;
  • /proc/sys/kernel/random/uuid potrebbe non essere disponibile su alcuni sistemi;
  • solo le lettere minuscole diventano così facili (è necessario un passaggio aggiuntivo per ottenere lettere maiuscole).

0

Una fodera (bash)

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

risultato

$ echo $mac
93:72:71:0B:9E:89
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.