有没有更好的方法可以从arp表中获取mac地址



我想使用 IP 地址从 arp 表中获取 mac 地址。目前我正在使用这个命令

arp -a $ipAddress | awk '{print $4}'

此命令打印我想要的内容。但我对此感到不舒服,我想知道是否有任何内置方法或更稳定的方式来做到这一点。

您可以使用

awk解析/proc/net/arp文件:

awk "/^${ipAddress//./.}>/"' { print $4 }' /proc/net/arp

但我不确定它是否更简单(不过它节省了一个分叉和一个子壳)。

如果您想要 100% bash 解决方案:

while read ip _ _ mac _; do
    [[ "$ip" == "$ipAddress" ]] && break
done < /proc/net/arp
echo "$mac"

好吧,你可以编写一个程序(例如在C中)来实际使用ARP协议(是的,我知道这是多余的,如ATM机或PIN码)本身来获取信息,但这可能比简单的管道要困难得多。

也许你应该更严格地检查你的舒适度,因为它可能会给你带来一些不必要的努力:-)

Linux ARP

内核模块的手册页列出了几种操作或读取 ARP 选项卡的方法,ioctl可能是最简单的方法。

arp -a的输出取决于语言环境(即它随系统语言而变化)。因此,至少将其强制为默认区域设置可能是个好主意:

LC_ALL=C arp -a $ipAddress | awk '{print $4}'

但是,我和你一样担心arp -a的输出不应该被解析。如果您的程序仅限于 linux 系统,另一种选择是解析文件/proc/net/arp 。此文件由内核导出,是 arp 本身解析以获取其信息的文件。该文件的格式在手册页 proc(5) 中有描述, 参见 man 5 proc 。这可以通过awk轻松完成:

awk '$1==IPADDRESS {print $4}' /proc/net/arp

这是一个awk + sed解决方案,它不假设列号总是4。

#!/bin/bash
cat /proc/net/arp |
    # remove space from column headers
    sed 's/([^ ])[ ]([^ ])/1_2/g' |
    # find HW_address column number and/or print that column
    awk '{
        if ( !column ) {
            for (i = 1; i <= NF; i++ ) {
                if ( $i ~ /HW_address/ ) { column=i }
            };
            print $column
         }
         else {
            print $column
         }
    }'

这里仍然存在脆弱的假设,例如列名是"硬件地址"。

更新,删除了 PIPE

sed -nr 's/^'${ipAddress//./.}'.*(([0-9A-Za-z]{2}:){5}[0-9A-Za-z]{2}).*$/1/p' /proc/net/arp

非固定柱溶液;

arp -a $ipAddress | sed -n 's/^.*(([0-9A-Z]{2}:){5}[0-9A-Z]{2}).*$/1/p'

解释

  • ^.* - 匹配字符串^的开头,后跟任何字符.*
  • [0-9A-Z]{2}: - 匹配数字字母数字的任何字符两次,后跟冒号。
  • ([0-9A-Z]{2}:){5} - 将( )之间的模式匹配五次。
  • [0-9A-Z]{2} - 匹配数字字母数字的任何字符两次。
  • .*$ - 匹配任何字符零次或多次.*直到字符串$末尾。
  • 1/p - 返回捕获模式 1/p打印匹配项。

您可以使用这个脚本:

awk ' $1~/[[:digit:]]/ {print $4}' /proc/net/arp

它的作用:

  1. 读取/proc/net/arp(标准 ARP 输出)

  2. 搜索带有 [0-9] 的字符串

  3. 使用Mac地址获取第4个"列"

享受!

我更喜欢使用 arping 命令显式查询某个 IP 地址的 MAC(这也更新了本地 ARP 缓存):

 arping -c 1 192.168.2.24 | grep -Eo "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]"

查找是否存在两个或多个主机使用相同的 IP 地址(添加 -D 选项)或使用简单的脚本检查本地 VLAN 中使用的当前 IP 地址非常有用,如下所示:

for i in $(seq 1 254); do 
    IP="192.168.5.$i"
    MAC=$(arping -c 1 $IP | grep -Eo "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]")
    if [ "$MAC" ] ; then
        echo "$IP $MAC"
    fi
done

请注意,arping无法以这种方式检测本地主机的 IP 地址(但我们可以在脚本中添加检查以显示它(如果范围内存在)。

arping有多个版本,选项和输出略有不同。在 Linux Ubuntu 中,一个在软件包 iputils-arping 中,另一个在软件包 arping 中。

注意:要回答问题而不是问题,在过滤/proc/net/arp时,您必须使用确保完全匹配的正则表达式,例如以空格结尾表达式(否则,在本例中,它还会显示 2.240-2.249 地址(如果存在):

ipaddress="192.168.2.24"
grep "^${ipaddress} " /proc/net/arp | grep -Eo "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]")

相关内容

  • 没有找到相关文章

最新更新