How to generate a valid random MAC Address with bash shell

How can i generate a valid random mac adress with bash.

The first half of the adress should always stay same like this

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

just the x value should be generated random?


Solution 1:

In the past I've done this using:

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

but that will only make them in the range 0-9. For my purposes, that was good enough.

Probably a better solution would be to use printf:

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

Here's how that works:

  • The printf program is based on the C "printf" function, which takes a "format string" as the first parameter and then additional parameters fill in the format string.
  • % in the format string introduces a "format specifier" which can be one or more characters telling how to format the arguments.
  • A leading zero (0) in a format specifier means that the resulting numeric output should be padded with leading zeros up to the specified width.
  • The 2 says that the specifier should be displayed taking up two characters worth of width.
  • The X ends the specifier and denotes that it should be interpreted as a number and displayed as hexidecimal. Because it's upper-case, the letters a-f should be upper case.
  • The \n is a newline -- printf interprets backslash as an escape code which can be used to display other characters, often tricky characters like the newline.
  • The remaining characters in the format specifier are printed out literally, this includes the initial "00-06-2F-" and the dashes between the format specifiers.
  • The remaining arguments are shell variable substitutions (denoted by the $) and include a math expression which is a random number (RANDOM) modulo 256. This results in a random number between 0 and 255.

Solution 2:

Here is a fish.

This shell script will generate the random string you seek:

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

I did just have something here that showed how to run it from the command line, but after looking at Dennis Williamson convoluted (but upvoted) solution I see that the answer that people expect is the one where they don't have to do any work themselves.

Solution 3:

  1. Generate an appropriately sized int like so: http://tldp.org/LDP/abs/html/randomvar.html
  2. Convert to hex like so: http://snipplr.com/view/2428/convert-from-int-to-hex/
  3. Add the dashes between three randomly generated chunks
#!/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

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

Note that the python version only uses a 16 wide field to generate a hex char, so you don't have to worry about zero padding - approach amended to address a comment.