如何使用bash shell生成有效的随机MAC地址


17

我如何使用bash生成有效的随机mac地址。

地址的前半部分应始终像这样保持不变

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

只是x值应该随机生成?


10
echo -n 00-60-2F; dd bs=1 count=3 if=/dev/random 2>/dev/null |hexdump -v -e '/1 "-%02X"'
artistoex 2012年

1
@artistoex真是太好了...您为什么不将其发布为答案?
bobmagoo 2012年

Answers:


18

这是一条鱼。

该shell脚本将生成您要查找的随机字符串:

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

我只是在这里展示了如何从命令行运行它的内容,但是在看了丹尼斯·威廉姆森令人费解(但被否决)的解决方案之后,我看到人们期望的答案是他们不必做任何工作的答案他们自己。


感谢您意识到我试图让他学会钓鱼而不是用勺子喂食解决方案
RobotHumans 2010年

1
您可以随时解释您的答案,以便除了在本次课程中提供一个钓鱼之外,还都在教他如何钓鱼...
Jed Daniels

该脚本的运行速度比hbdgaf提出的脚本快得多,并且不会在1000次循环中生成任何无效的MAC地址。谢谢!
Bruno Finger

1
您的解决方案有效,只有3行。我卖了
理查德·戈麦斯

17

过去,我使用以下方法完成此操作:

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

但这只会使它们的范围为0-9。对我而言,这已经足够了。

可能更好的解决方案是使用printf:

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

运作方式如下:

  • printf程序基于C“ printf”函数,该函数将“格式字符串”作为第一个参数,然后使用其他参数填充格式字符串。
  • 格式字符串中的%引入了“格式说明符”,该说明符可以是一个或多个字符,指示如何格式化参数。
  • 格式说明符中的前导零(0)表示结果数字输出应填充前导零,直至指定宽度。
  • 2表示说明符应显示为两个宽度的字符。
  • X结束说明符,表示应将其解释为数字并显示为十六进制。因为是大写字母,所以字母af应该是大写字母。
  • \ n是换行符-printf将反斜杠解释为转义码,可用于显示其他字符,通常是诸如换行符之类的棘手字符。
  • 格式说明符中的其余字符将原样打印出来,其中包括开头的“ 00-06-2F-”和格式说明符之间的破折号。
  • 其余参数是shell变量替换(用$表示),并包括一个数学表达式,该表达式为256模的随机数(RANDOM)。这将导致0到255之间的随机数。

2
正如user58033在答案中正确指出的那样(现在可能已经不存在了):%02X将给出一个大写字母。
Arjan 2010年

啊,好点。我隔开了原始问题,给出了一个使用大写字母的示例。感谢您的欢迎。:-)
肖恩·赖夫施耐德

如果您可以解释正在发生的事情以及您的解决方案为何起作用,则额外+1。
杰德·丹尼尔斯

你去了,@杰德。
肖恩·赖夫施耐德

17
  1. 生成一个适当大小的int,如下所示:http : //tldp.org/LDP/abs/html/randomvar.html
  2. 像这样转换为十六进制:http : //snipplr.com/view/2428/convert-from-int-to-hex/
  3. 在三个随机生成的块之间添加破折号
#!/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

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

请注意,python版本仅使用16个宽域来生成十六进制字符,因此您不必担心零填充-修改方法可解决注释。


如果您提供每一个的示例,则额外+1(我知道您正在教他如何钓鱼,但是您可以将拼图的各个部分拼凑在一起,并说明它们的工作方式/原因。)
Jed Daniels

@杰德·丹尼尔斯-完成了。提供的代码。
RobotHumans 2011年

这段代码为我生成了一些无效的MAC。它循环1000次我有几个类似的MAC 00-60-2F-8B-5-2C00-60-2F-A-71-9700-60-2F-82-F1-4
Bruno Finger

自从OP坚持要进行重击以来,这就是我扔出去的东西。您是说您不知道如何用零填充空格?@BrunoFinger
RobotHumans 2015年

可以很容易地改写为使用16而不是255并生成零占位符。它只是更多的行...
RobotHumans 2015年

12

使用标准工具

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

要么

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

可能是最短的。


您能否在答案中描述od的确切功能?也可以通过其他方式使用它!
布鲁诺·比耶里

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"

运作方式的关键:

  • LC_CTYPE=C -允许字符> 0x7F
  • IFS=-禁用对\t(制表符),\n(换行符)和空格的解释
  • -d ''-允许换行
  • -r允许\(并且几乎应始终习惯与配合使用read
  • 格式说明符-%02x\n使输出为文字连字符,后接两位十六进制数字,包括前导零(如果适用)。换行在这里是多余的,可以省略。
  • read得到一个单一的字节(-n 1从)/dev/urandom中的范围为0〜255(00FF)。
  • printf循环中最后一个参数中的单引号引起字符以其数值输出(“ A”输出为“ 65”)。请参阅POSIX规范printf中的说明:

    如果前导字符是单引号或双引号,则该值应是单引号或双引号后面字符的基础代码集中的数值。


这似乎需要IFS= read …避免折叠09 0A和20(通常的IFS字符)转换成00
克里斯约翰森

@Chris:对不起,我在做一些双重检查时拿出了几样东西,忘了放回去。这也是需要的-d ''。我会解决我的答案。谢谢你让我知道。
暂停,直到另行通知。

糟糕,-r保护`\`的掉了。我希望在shell程序中正确处理二进制数据不是那么麻烦。seems似乎无法在字符串中间准确表示00。您一次的单字符方法通过read字符串插值以及如何printf处理单字符参数之间的便捷(设计的)协作来处理00 '。叹。
克里斯·约翰森

@Chris:希望我的DWIM处理器没有问题。顺便说一句,您可能会感兴趣的是看到我编写的纯Bash脚本,该脚本复制了的核心功能hexdump -C
暂停,直到另行通知。

如果您可以解释正在发生的事情以及您的解决方案为何起作用,则额外+1。
杰德·丹尼尔斯

7

我想出的最短方法是直接使用hexdump

echo 00-60-2f$(hexdump -n3 -e '/1 "-%02X"' /dev/random)
  • -n3告诉hexdump读取三个byytes
  • 格式字符串为每个字节打印破折号和两位数的十六进制值
    • / 1表示对每个读取字节应用格式
    • “-%02X”是用于打印前导零,两位数字,大写十六进制值的printf规范
  • / dev / random是源随机字节

在GNU / Linux上测试


Unix的有效性:-)
artistoex 2012年

hexdump -n3 -e'/3 "00-60-2F" 3/1 "-%02X"' /dev/random短一点:-)
artistoex

4

另一种解决方案

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

大写相同

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

为Bash环境变量生成它

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

细节:

  • od(八进制转储)

    -An抑制输出的前导地址表示(额外的噪声)。
    -N3将输出限制为三个字节。
    -t xC根据需要以十六进制,ASCII字符样式输出。
    /dev/urandomLinux内核随机数伪文件。

  • sed(流编辑器)用于用空格替换连字符。

    -e <SCRIPT> 执行sed脚本。

  • tr(字符串翻译)在此示例中为可选。我喜欢脚本/环境中的大写MAC地址。


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

这应该工作

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
如果您可以解释正在发生的事情以及您的解决方案为何起作用,则额外+1。
Jed Daniels


0

这是经典shell(#!/bin/sh)脚本中的工作方式:

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

或者,如果您想使用自定义前缀:

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
}

用法示例:

$ 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

另一种选择是使用jot

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

-w更改格式,-s更改分隔符并-r生成随机数。

od由artistoex和zero2cx发布的答案中使用的命令会在OS X的输出中添加额外的破折号od,但这不是:

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

OS X od/usr/bin/od以下)使用与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
当心记笔记。我通过这种方式生成了一些具有“ 100”的mac,例如00-60-2F-100-A3-F6 ...
petrus

@petrus是的,我编辑了答案,将其更改jot -w%02X -s- -r 3 1 256jot -w%02X -s- -r 3 0 256
nisetama

0

在Linux中:

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

说明:

在Linux中,每次阅读时都会/proc/sys/kernel/random/uuid返回一个新的类型4(随机)的UUID。它的大多数字符都是(伪)随机十六进制数字,因此我们可以使用它们。例如:

$ 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

现在就足以先打印00-60-2f-(没有换行符):

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

优点:

  • 从一开始就使用十六进制数字,无需转换/过滤;
  • printf并且cut是POSIX工具;
  • (针对您的特定情况)UUID中已经有连字符,我们使用它们。

缺点:

  • 我们需要注意UUID中的两个非随机数字;
  • /proc/sys/kernel/random/uuid 在某些系统上可能不可用;
  • 只有小写字母变得如此容易(您需要额外的步骤来获取大写字母)。

0

一支衬板(重击)

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

结果

$ echo $mac
93:72:71:0B:9E:89
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.