【问题标题】:Get MAC address using shell script使用 shell 脚本获取 MAC 地址
【发布时间】:2023-06-29 00:58:01
【问题描述】:

目前所有提到的获取 MAC 地址的解决方案都是使用 eth0。 但是,如果我的接口不是以 eth1 开头,而不是 eth0 怎么办。同样在 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 而不是 eth0 的 HWaddr。 我如何找到它?它还应该适用于所有 Linux 风格。

【问题讨论】:

    标签: linux shell mac-address


    【解决方案1】:

    注意接口名称和 MAC 地址是一行中的第一个和最后一个字段,没有前导空格。

    如果其中一个缩进行包含inet addr:,则应打印最新的接口名称和 MAC 地址。

    ifconfig -a |
    awk '/^[a-z]/ { iface=$1; mac=$NF; next }
        /inet addr:/ { print iface, mac }'
    

    请注意,多个接口可以满足您的条件。然后,脚本将打印多行。 (如果您总是只想打印第一个匹配项,则可以在最后一个右大括号之前添加 ; exit。)

    【讨论】:

    • 如果您的目标仅是 Linux,则直接检查相关的 /proc 条目会更可靠;但既然你也提到了 OSX,我想这种方法被排除了。
    【解决方案2】:

    你可以这样做

    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
    

    【讨论】:

      【解决方案3】:

      哦,如果你只想要mac ether mac地址,你可以使用它:

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

      (在 Macintosh 上工作)

      • ifconfig -- 获取所有信息
      • grep -- 与地址保持一致
      • tr -- 全部清除
      • cut -- 去掉“ether”,只有地址

      【讨论】:

      • tr -d 可以一次性删除多个字符。正则表达式 ether* 匹配 ethe 后跟零次或多次出现的 r;我想您的意思是 grep 'ether' 与输入行上任意位置的文字字符串匹配。 ifconfig | grep ether | tr -d ' \t' | cut -c 6-42
      • 就像我回答中的 Awk 一样,它在单个进程中执行几乎相同的操作,而不是调用多个进程的管道。
      【解决方案4】:

      针对 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 这样的虚拟文件系统接口。

      【讨论】:

      • 这应该是最好的答案!
      【解决方案5】:

      获取 eth0 的 MAC 地址:

      $ cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep HWADDR | cut -c 9-25
      

      例子:

      [me@machine ~]$ cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep HWADDR | cut -c 9-25
      55:b5:00:10:be:10
      

      【讨论】:

      • grep 可以很好地读取输入文件。避免使用useless use of cat
      • 仅限于 Redhat 衍生产品。
      • 这可能是错误的,因为 ifcfg-eth0 只是特定接口/mac 地址的配置文件,而不是实际的接口/mac。
      【解决方案6】:
      $ ip route show default | awk '/default/ {print $5}'
      

      return:eth0(我的在线界面)

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

      return:ec:a8:6b:bd:55:05(eth0的mac地址,我的在线界面)

      Terminal image

      【讨论】:

      • 欢迎来到 *。请发布有关您的答案的更多信息。它在做什么以及为什么。
      • 我认为的最佳答案。其他的要么一直不工作,要么依赖于固定的接口名称。
      • 应该是公认的答案。恕我直言,它的作用非常简单,不需要解释。也就是说,这个解决方案依赖于ip route 输出格式。
      • 也认为这应该是公认的答案,可能有一些版本或使用 ip add 命令
      • 感谢您的回答,这正是我想要的;一种在不知道接口的情况下获取 MAC 地址的方式。 +1
      【解决方案7】:

      在现代 GNU/Linux 系统上,您可以查看可用的网络接口列出 /sys/class/net/ 的内容,例如:

      $ ls /sys/class/net/
      enp0s25  lo  virbr0  virbr0-nic  wlp2s0
      

      您可以检查接口是否为up,查看设备目录中的operstate。例如,您可以通过以下方式查看 enp0s25 是否已启动:

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

      然后您可以通过以下方式获取该接口的 MAC 地址

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

      例如,这是一个打印活动接口 MAC 地址的简单 bash 脚本:

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


      还请记住,从 2015 年起,大多数 GNU/Linux 发行版都切换到 systemd,并且不再使用 ethX 接口命名方案 - 现在它们使用基于硬件拓扑的更强大的命名约定,请参阅:

      【讨论】:

        【解决方案8】:

        如果上面列出的答案不适合您,这里有一个替代答案。您也可以使用以下解决方案,该解决方案位于here

        ip addr
        

        ip addr show
        

        ip link
        

        所有这三个都将在link/ether 旁边显示您的 MAC 地址。我偶然发现了这一点,因为我刚刚从没有互联网访问的 USB 记忆棒完成了 Debian 9.5 的全新安装,所以我只能进行非常小的安装,并收到了

        -bash: ifconfig: command not found
        

        当我尝试了上述一些解决方案时。我想其他人也可能遇到这个问题。希望对您有所帮助。

        【讨论】:

          【解决方案9】:

          简单运行:

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

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

          这两个示例命令将 grep 带有“ether”字符串的所有行,并在 grep 部分的数字空格(在 -f 选项中指定)之后剪切 mac 地址(我们需要)。

          在不同的 Linux 风格上测试

          【讨论】:

            【解决方案10】:

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

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

            祝你有美好的一天!

            【讨论】:

            • 哇!谢谢!这正是我在 vultr 上获取私有网络 mac 地址所要寻找的。​​span>
            【解决方案11】:

            以上方法都不适合我,因为我的设备处于 balance-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
            

            【讨论】:

              【解决方案12】:

              我使用命令 hciconfig 和两个 grep 来分隔 PC Mac 地址,并且我将 MAC 地址保存到变量

              PCMAC=$( hciconfig -a | grep -E 'BD Address:' | grep -Eo '[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}' )

              您也可以使用此命令检查 MAC 地址的格式是否有效。请注意,只允许使用大字符 AF,您还需要为此 grep 命令添加输入:

              grep -E '[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}'

              【讨论】:

                【解决方案13】:

                这是在 Armbian 上唯一对我有用的东西:

                dmesg | grep -oE 'mac=.*\w+' | cut -b '5-'
                

                【讨论】:

                  【解决方案14】:

                  这是我的解决方案:

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

                  【讨论】: