使用代码/Python读取Linux ARP表的最简单方法



我有一个在Linux上运行的Python脚本,它需要重复可靠地读取ARP表,以便检查一些IP-MAC关联。我正在评估可能的选择,并想知道其中哪一个是最精简/最干净的——主要是在性能和开销方面。

以下内容目前在我的雷达上:

  1. 使用subprocess运行arp -an并解析输出
  2. 读取/proc/net/arp并解析输出(类似于#1,但获取底层数据的方式不同;像python_apptable这样的库正是这样做的(
  3. 打开一个套接字并使用SIOCGARPioctl系统调用轮询ARP表(根据http://man7.org/linux/man-pages/man7/arp.7.html)。我还没有这方面的Python实现,但相信这是可行的
  4. 使用subprocess运行ip neighbor list并解析输出
  5. 使用类似pyrote2的Python网络链接库来读取该表

如果我没有错的话,选项#1和#2直接从内核缓存读取表,选项#4和#5使用netlink调用;我不太确定3号落在哪里。

有一段时间,我在做#5——特别是使用pyrote2——但遇到了一些可靠性问题;例如,肯定存在的ARP条目没有被列出。我有一种感觉,pyrote2对于手头的简单任务来说可能有点太强大了。我目前正在做#2,目前看起来效果不错,但不知道是否有更好的方法。

尽管我的实现语言是Python,但我相信这个问题并不是针对特定语言的。我很乐意就以上的优点和缺点提供一些建议。具体而言:

  • 最好运行命令并读取其输出,还是从/proc读取文件?(选项#1与#2(
  • 老派内核vs新时代网络链接?(#1/2 vs#4/5(
  • ioctl方法(#3(与其他方法相比如何

我在寻找类似的解决方案时发现了这个问题。这是我决定的一个MRE:

arp_cmd=["cat", "/proc/net/arp"]
proc = subprocess.Popen(arp_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(arp_cache, arp_err) = proc.communicate()
arp_entries = arp_cache.decode().split("n")
for entry in arp_entries.copy():
if not entry.startswith("IP address"):
ip = entry.split()[0]
mac = entry.split()[3]
mac_if = entry.split()[5]
print("IP:", ip)
print("mac:" mac)
print("mac_if:" mac_if)

最新更新