我想通过使用 ip 地址从 arp 表中获取一个 mac 地址。目前我正在使用这个命令
arp -a $ipAddress | awk '{print $4}'
这个命令打印我想要的。但我对此并不满意,我想知道是否有任何内置方式或更稳定的方式来做到这一点。
您可以使用以下方法解析/proc/net/arp
文件awk
:
awk "/^${ipAddress//./\.}\>/"' { print $4 }' /proc/net/arp
但我不确定它是否更简单(虽然它节省了一个叉子和一个子shell)。
如果你想要一个 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
}
}'
这里仍然有一些脆弱的假设,例如列名是“HW 地址”。
更新,移除了 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
它的作用:
读取 /proc/net/arp(标准 arp 输出)
搜索带有 [0-9] 的字符串
使用 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]")