使用Shell脚本获取MAC地址

47

目前提到获取MAC地址的所有解决方案都是使用eth0。但是如果我的接口以eth1开头怎么办?另外,在OS X上,接口名称也不同。
此外,接口eth0可能存在但未使用。即它未激活,没有IP。

那么有没有一种方法可以获取第一个可用接口的MAC地址。(即它具有inet地址,我甚至不想要一个具有inet6的地址)。

例如

eth0      Link encap:Ethernet  HWaddr <some addr>
          inet6 addr: <some addr> Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:123
          RX packets:123 errors:123 dropped:123 overruns:123 frame:123
          TX packets:123 errors:123 dropped:123 overruns:123 carrier:123
          collisions:123 txqueuelen:123 
          RX bytes:123 (123 MB)  TX bytes:123 (123 KB)
          Interrupt:123 Memory:00000000-00000000

eth1      Link encap:Ethernet  HWaddr <some addr>
          inet addr:<some addr>  Bcast:<some addr>  Mask:<some addr>
          inet6 addr: <some addr> Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:123 Metric:123
          RX packets:123 errors:123 dropped:123 overruns:123 frame:123
          TX packets:123 errors:123 dropped:123 overruns:123 carrier:123
          collisions:123 txqueuelen:123 
          RX bytes:123 (123 MB)  TX bytes:123 (123 KB)
          Interrupt:123 Memory:00000000-00000000

注意:我已经更改了输出的值。

所以在这种情况下,我想要 eth1 的 HWaddr 而不是 eth0 的。 我该怎么找到它?另外,它应该适用于所有 Linux 发行版。

14个回答

96

您可以按照以下步骤进行操作

ifconfig <Interface ex:eth0,eth1> | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'

你也可以按照如下方式获取所有接口的MAC地址

cat /sys/class/net/*/address

对于特定的接口,比如eth0

cat /sys/class/net/eth0/address

60

最佳的 Linux 特定解决方案是使用 sysfs:

$ IFACE=eth0
$ read MAC </sys/class/net/$IFACE/address
$ echo $IFACE $MAC
eth0 00:ab:cd:12:34:56

相比其他方法,这种方法非常干净,并且不会产生额外的进程,因为read是POSIX shell(包括非BASH shell)的内置命令。但是,如果您需要在OS X中实现可移植性,则必须使用ifconfigsed方法,因为OS X没有像sysfs那样的虚拟文件系统接口。


3
这应该是最好的答案! - Bruno Duyé

51
$ ip route show default | awk '/default/ {print $5}'

返回: eth0(我的在线接口)

$ cat /sys/class/net/$(ip route show default | awk '/default/ {print $5}')/address

返回:ec:a8:6b:bd:55:05 (eth0的mac地址,即我的在线接口)

终端图像


2
欢迎来到 Stackoverflow。请在您的回答中提供更多信息。它是做什么的,为什么要这样做。 - Whitecat

20
在现代的GNU/Linux系统中,您可以通过查看 /sys/class/net/ 的内容,查看可用的网络接口列表,例如:
$ ls /sys/class/net/
enp0s25  lo  virbr0  virbr0-nic  wlp2s0

您可以通过查看设备目录中的operstate来检查接口是否处于up状态。例如,以下是如何查看enp0s25是否处于up状态:

$ cat /sys/class/net/enp0s25/operstate
up

你可以使用以下命令获取该接口的MAC地址:

$ cat /sys/class/net/enp0s25/address 
ff:00:ff:e9:84:a5

例如,这里有一个简单的Bash脚本,它会打印出活动接口的MAC地址:
#!/bin/bash
# getmacifup.sh: Print active NICs MAC addresses
D='/sys/class/net'
for nic in $( ls $D )
do
    echo $nic
    if  grep -q up $D/$nic/operstate
    then
        echo -n '   '
        cat $D/$nic/address
    fi
done

下面是在一个同时拥有以太网和wifi接口的系统上运行该程序的输出:

$ ./getmacifup.sh
enp0s25
   ff:00:ff:e9:84:a5
lo
wlp2s0

具体详见Kernel文档


另外需要注意,自2015年起,大多数GNU/Linux发行版已经转换到了使用systemd,不再使用以ethX命名接口的方案——现在它们使用更健壮的基于硬件拓扑的命名约定,详见:


12
请注意,接口名称和MAC地址是一行中没有前导空格的第一个和最后一个字段。 如果缩进的行之一包含inet addr:,则应打印最新的接口名称和MAC地址。
ifconfig -a |
awk '/^[a-z]/ { iface=$1; mac=$NF; next }
    /inet addr:/ { print iface, mac }'

请注意,可能有多个接口符合您的条件。然后,脚本将打印多行。(如果您始终只想打印第一个匹配项,可以在最后一个闭括号之前添加; exit。)

如果你的目标仅限于Linux,直接检查相关的/proc条目会更加健壮;但是由于你也提到了OSX,我想这种方法已经被排除了。 - tripleee

7

只需运行以下命令:

ifconfig | grep ether | cut -d " " -f10

或者

ip a | grep ether | cut -d " " -f6

以下两个示例命令将grep所有包含"ether"字符串的行,并根据指定在-grepped部分中数字空格(在-f选项中)后面的mac地址(我们需要)。

已在不同的Linux版本上进行测试


4

我知道这有点过时了,但是通过基本命令,我们可以获取接口的MAC地址:

ip link show eth0 | grep link/ether | awk '{print $2}'

祝您有美好的一天!


哇!谢谢!那正是我在 Vultr 上获取私有网络 MAC 地址所寻找的。 - insign

3

如果您仅需要Mac地址,可以使用以下命令:

ifconfig | grep "ether*" | tr -d ' ' | tr -d '\t' | cut -c 6-42

(在Macintosh上工作)

  • ifconfig -- 获取所有信息
  • grep -- 保留具有地址的行
  • tr -- 清除所有内容
  • cut -- 删除“ether”,只保留地址

tr -d can remove multiple characters in one go. The regex ether* matches ethe followed by zero or more occurrences of r; I suppose you really mean grep 'ether' which matches the literal string anywhere on the input line. ifconfig | grep ether | tr -d ' \t' | cut -c 6-42 - tripleee
就像我回答中的Awk一样,它可以在单个进程中完成相同的操作,而不是通过管道调用多个进程。 - tripleee

1

这是我的解决方案:

 ip a | grep link/ether | awk -F " " '{print $2}'

1

以上方法都对我无效,因为我的设备处于平衡rr绑定状态。使用ip l lifconfig/sys/class/net/${device}/address查询结果会显示相同的MAC地址,因此其中一个是正确的,另一个是未知的。

但如果您没有重命名设备(有什么提示我错过了吗?):

udevadm info -q all --path "/sys/class/net/${device}"

即使您将其重命名(例如:ip l set name x0 dev p4p1),此方法仍然有效:
cat /proc/net/bonding/bond0

或者我的丑陋脚本可以使其更易解析(未经测试的驱动程序/操作系统/任何兼容性):
awk -F ': ' '
         $0 == "" && interface != "" {
            printf "%s %s %s\n", interface, mac, status;
            interface="";
            mac=""
         }; 
         $1 == "Slave Interface" {
            interface=$2
         }; 
         $1 == "Permanent HW addr" {
            mac=$2
         };
         $1 == "MII Status" {
            status=$2
         };
         END {
            printf "%s %s %s\n", interface, mac, status
         }' /proc/net/bonding/bond0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接