我想使用 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
它的作用:
读取/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]")