Comment générer une adresse MAC aléatoire valide avec le shell bash


17

Comment puis-je générer une adresse mac aléatoire valide avec bash.

La première moitié de l'adresse doit toujours rester la même comme celle-ci

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

juste la valeur x doit être générée au hasard?


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 C'était magnifique ... Pourquoi n'avez-vous pas posté cela comme réponse?
bobmagoo

Réponses:


18

Voici un poisson.

Ce script shell va générer la chaîne aléatoire que vous recherchez:

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

J'avais juste quelque chose ici qui montrait comment l'exécuter à partir de la ligne de commande, mais après avoir regardé la solution compliquée (mais votée) de Dennis Williamson, je vois que la réponse que les gens attendent est celle où ils n'ont pas à faire de travail se.


merci d'avoir réalisé que j'essayais de lui faire apprendre à pêcher au lieu de nourrir à la cuillère une solution
RobotHumans

1
Vous pourriez toujours expliquer votre réponse afin que vous lui appreniez tous les deux à pêcher en plus d'en fournir une cette fois-ci ...
Jed Daniels

Ce script s'exécute beaucoup plus rapidement que celui proposé par hbdgaf et ne génère aucune adresse MAC invalide dans une boucle de 1000 fois. Merci!
Bruno Finger

1
Votre solution fonctionne et ne dispose que de 3 lignes. Je suis vendu.
Richard Gomes

17

Dans le passé, je l'ai fait en utilisant:

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

mais cela ne les rendra que dans la plage de 0 à 9. Pour mes besoins, c'était assez bon.

Une meilleure solution serait probablement d'utiliser printf:

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

Voici comment cela fonctionne:

  • Le programme printf est basé sur la fonction C "printf", qui prend une "chaîne de format" comme premier paramètre, puis des paramètres supplémentaires remplissent la chaîne de format.
  • % dans la chaîne de format introduit un "spécificateur de format" qui peut être un ou plusieurs caractères indiquant comment formater les arguments.
  • Un zéro de tête (0) dans un spécificateur de format signifie que la sortie numérique résultante doit être complétée avec des zéros de tête jusqu'à la largeur spécifiée.
  • Le 2 indique que le spécificateur doit être affiché en prenant deux caractères de largeur.
  • Le X termine le spécificateur et indique qu'il doit être interprété comme un nombre et affiché en hexadécimal. Parce qu'il s'agit de majuscules, les lettres af doivent être en majuscules.
  • Le \ n est une nouvelle ligne - printf interprète la barre oblique inverse comme un code d'échappement qui peut être utilisé pour afficher d'autres caractères, souvent des caractères délicats comme la nouvelle ligne.
  • Les caractères restants dans le spécificateur de format sont imprimés littéralement, cela inclut le "00-06-2F-" initial et les tirets entre les spécificateurs de format.
  • Les arguments restants sont des substitutions de variables shell (désignées par $) et incluent une expression mathématique qui est un nombre aléatoire (RANDOM) modulo 256. Il en résulte un nombre aléatoire compris entre 0 et 255.

2
Comme l'a souligné à juste titre user58033 dans une réponse (qui pourrait disparaître maintenant): %02Xdonnerait une lettre majuscule.
Arjan

Ah, bon point. J'ai espacé que la question d'origine donnait un exemple en utilisant des majuscules. Merci pour l'accueil. :-)
Sean Reifschneider

Extra +1 si vous pouvez expliquer ce qui se passe et pourquoi votre solution fonctionne.
Jed Daniels

Voilà, @Jed.
Sean Reifschneider

17
  1. Générez un int de taille appropriée comme ceci: http://tldp.org/LDP/abs/html/randomvar.html
  2. Convertissez en hexagone comme ceci: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Ajoutez les tirets entre trois morceaux générés aléatoirement
#!/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

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

Notez que la version python utilise uniquement un champ large de 16 pour générer un caractère hexadécimal, vous n'avez donc pas à vous soucier du remplissage nul - approche modifiée pour répondre à un commentaire.


Extra +1 si vous fournissez un exemple de chacun (je sais que vous lui apprenez à pêcher, mais vous pouvez lui donner les pièces du puzzle à assembler et expliquer comment / pourquoi elles fonctionnent).
Jed Daniels

@Jed Daniels - terminé et terminé. code fourni.
RobotHumans

Ce code génère pour moi quelques MAC invalides. Bouclant 1000 fois je suis arrivé quelques MACs comme 00-60-2F-8B-5-2C, 00-60-2F-A-71-97, 00-60-2F-82-F1-4.
Bruno Finger

C'est juste quelque chose que j'ai jeté là-bas depuis que le PO insistait sur bash. Vous dites que vous ne pouvez pas comprendre comment remplir les chiffres simples avec un zéro à droite? @BrunoFinger
RobotHumans

Peut être facilement retravaillé pour utiliser 16 au lieu de 255 et générer l'espace réservé zéro. C'est juste plus de lignes ...
RobotHumans

12

À l'aide d'outils standard, soit

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

ou

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

pourrait être le plus court de tous.


Pouvez-vous décrire dans votre réponse ce que fait exactement od? Il serait également utile de l'utiliser de différentes manières!
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"

Les clés du fonctionnement:

  • LC_CTYPE=C - autorise les caractères> 0x7F
  • IFS=- désactive l'interprétation de \t(tab), \n(nouvelle ligne) et de l'espace
  • -d ''- permet les sauts de ligne
  • -rpermet \(et devrait presque toujours être utilisé par habitude avecread )
  • Le spécificateur de format -%02x\n fait que la sortie est un tiret littéral suivi d'un nombre hexadécimal à deux chiffres incluant un zéro de tête, le cas échéant. La nouvelle ligne est superflue ici et pourrait être omise.
  • Le readobtient un seul octet ( -n 1) de /dev/urandom0 à 255 ( 00à FF).
  • Le guillemet simple dans le dernier argument de printfdans la boucle fait que le caractère est sorti comme sa valeur numérique ("A" est sorti comme "65"). Voir la spécification POSIX pour savoirprintf où il est indiqué:

    Si le premier caractère est un guillemet simple ou un guillemet double, la valeur doit être la valeur numérique dans le jeu de codes sous-jacent du caractère suivant le guillemet simple ou le guillemet double.


Il semble qu'il faut IFS= read …éviter de replier 09 0a et 20 (les caractères IFS habituels) en 00.
Chris Johnsen

@Chris: Désolé, j'ai retiré deux ou trois choses en faisant une double vérification et j'ai oublié de les remettre. Il faut aussi -d ''. Je vais corriger ma réponse. Merci de me le faire savoir.
pause jusqu'à nouvel ordre.

Oups, le -rqui protège `` est tombé. Je souhaite que la bonne gestion des données binaires dans les programmes shell ne soit pas si compliquée. ☺ Il semble impossible de représenter avec précision 00 au milieu de la chaîne. Votre méthode à caractère unique à la fois gère 00 grâce à la coopération pratique (conçue?) Entre read, l'interpolation de chaînes et la façon dont printftraite l'argument à un caractère '. Soupir.
Chris Johnsen

@Chris: Je souhaite que mon processeur DWIM ne soit pas au rendez-vous. Soit dit en passant, vous pourriez être intéressé de voir un script Bash pur que j'ai écrit qui duplique la fonctionnalité de base de hexdump -C.
pause jusqu'à nouvel ordre.

Extra +1 si vous pouvez expliquer ce qui se passe et pourquoi votre solution fonctionne.
Jed Daniels

7

Le moyen le plus court que j'ai pu trouver était d'utiliser directement hexdump

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3 indique à hexdump de lire trois octets
  • La chaîne de format imprime un tiret et une valeur hexadécimale à deux chiffres pour chaque octet
    • '/ 1' signifie appliquer le format pour chaque octet lu
    • "-% 02X" est une spécification printf pour imprimer un zéro, deux chiffres, une valeur hexadécimale en majuscule
  • / dev / random est un octet aléatoire source

Testé sur GNU / Linux


L'efficacité d'Unix au travail :-)
artistoex

hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/randomest un peu plus court :-)
artistoex

4

Une autre solution en ligne

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

Même chose en majuscules

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

Générez-le pour une variable d'environnement Bash

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

Détails:

  • od (vidage octal)

    -AnSupprime la principale représentation d'adresse (bruit supplémentaire) de la sortie.
    -N3Limitez la sortie à trois octets.
    -t xCSortie en hexadécimal, style ASCII, comme vous le souhaitez.
    /dev/urandomPseudo-fichier à nombres aléatoires du noyau Linux.

  • sed (éditeur de flux) Pour la substitution d'espace à trait d'union.

    -e <SCRIPT> exécutez le script sed.

  • tr (traduction de chaîne) Facultatif, dans cet exemple. J'aime les adresses MAC majuscules dans mes scripts / environnement.


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

Cela devrait fonctionner

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 si vous pouvez expliquer ce qui se passe et pourquoi votre solution fonctionne.
Jed Daniels

0

Celui-ci fonctionne également. La sortie est tout en majuscules comme requis.

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

0

Cela fonctionne dans le #!/bin/shscript shell ( ) classique :

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

Ou, si vous souhaitez avoir un préfixe personnalisé:

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
}

Exemple d'utilisation:

$ 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

Une autre option consiste à utiliser jot:

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

-wmodifie le format, -smodifie le séparateur et-r génère des nombres aléatoires.

Les commandes utilisant oddans les réponses publiées par artistoex et zero2cx ajoutent des tirets supplémentaires à la sortie avec OS X od, mais cela ne fait pas:

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

OS X od( /usr/bin/odci-dessous) utilise un format de sortie différent de 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
Attention au jot. J'ai un mac généré de cette façon qui contient "100", par exemple 00-60-2F-100-A3-F6 ...
petrus

@petrus Vous avez raison, j'ai modifié la réponse pour passer jot -w%02X -s- -r 3 1 256à jot -w%02X -s- -r 3 0 256.
nisetama

0

Sous Linux:

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

Explication:

Sous Linux, /proc/sys/kernel/random/uuidrenvoie un nouvel UUID de type 4 (aléatoire) chaque fois que vous le lisez. La plupart de ses caractères sont des chiffres hexadécimaux (pseudo) aléatoires, nous pouvons donc les utiliser. Par exemple:

$ 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

Il suffit maintenant d'imprimer 00-60-2f-(sans nouvelle ligne) en premier:

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

Avantages:

  • chiffres hexadécimaux dès le début, aucune conversion / filtrage nécessaire;
  • printfet cutsont des outils POSIX;
  • (pour votre cas spécifique) des tirets déjà en UUID, nous les utilisons.

Les inconvénients:

  • nous devons faire attention aux deux chiffres non aléatoires dans UUID;
  • /proc/sys/kernel/random/uuid peut ne pas être disponible sur certains systèmes;
  • seules les lettres minuscules sont si faciles (vous avez besoin d'une étape supplémentaire pour obtenir les lettres majuscules).

0

Un liner (bash)

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

résultat

$ echo $mac
93:72:71:0B:9E:89
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.