【问题标题】:Detect wireless devices connected to Raspberry Pi in python on Linux在 Linux 上的 python 中检测连接到 Raspberry Pi 的无线设备
【发布时间】:2016-01-13 22:51:07
【问题描述】:

在我的 python 代码中,我需要获取连接到 Raspberry Pi 的“物理”WiFi 网络设备列表

我一直在这样做:

raw_output = check_output('iw dev', shell=True)

然后从raw_output提取我需要的所有数据

它工作正常,但在iw help 中它说Do NOT screenscrape this tool, we don't consider its output stable. 以我的方式获取这些数据真的不安全吗?如果是,正确的做法是什么?

【问题讨论】:

    标签: python linux shell network-programming raspberry-pi


    【解决方案1】:

    “不要截屏这个工具,我们认为它的输出不稳定”的意思是随着iw 的新版本的发布,输出格式可能会改变。所以iw 的开发者警告你,如果你根据输出的解析来编写软件,它可能会在iw 的未来版本中中断。

    以古老的ifconfig 命令为例。多年来,它的输出格式一直是这样的:

    eth0      Link encap:Ethernet  HWaddr 00:80:C8:F8:4A:51
              inet addr:192.168.99.35  Bcast:192.168.99.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:190312 errors:0 dropped:0 overruns:0 frame:0
              TX packets:86955 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:100 
              RX bytes:30701229 (29.2 Mb)  TX bytes:7878951 (7.5 Mb)
              Interrupt:9 Base address:0x5000
    

    虽然它被认为是稳定的(甚至被一些人弃用和维护),但它在几年前发生了变化,现在看起来像这样:

    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.1.67  netmask 255.255.255.0  broadcast 192.168.1.255
            inet6 fe80::8e89:a5ff:fe57:103c  prefixlen 64  scopeid 0x20<link>
            ether 8c:89:a5:57:10:3c  txqueuelen 1000  (Ethernet)
            RX packets 2219946  bytes 3178868967 (2.9 GiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 1241676  bytes 102998523 (98.2 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    ...假设我做了一些软件,通​​过搜索“HWaddr”后面的字符串来查看 MAC 地址。现在它会被破坏,因为它应该寻找“ether”之后的字符串。

    但只要你不更新iw,或者对你的工作进行定期测试,你应该不会遇到任何问题。

    无论如何总是解析第三方工具的输出本质上有点脆弱,你只需要注意它。例如,输出可能取决于用户的 LOCALE 设置。现实生活中的示例,我使用ifconfig 的输出编写的一些脚本在某些用户环境中失败。根本原因:以下是法语语言环境中的输出:

    eth0      Lien encap:Ethernet  HWaddr 00:FF:F2:58:32:A1  
              UP BROADCAST MULTICAST  MTU:1500  Metric:1
              Packets reçus:0 erreurs:0 :0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 lg file transmission:1000 
              Octets reçus:0 (0.0 b) Octets transmis:0 (0.0 b)
              Interruption:23 Adresse de base:0x2000
    

    注意法语的“Packets reçus”、“erreurs”和“Octets reçus”,而不是“RX packet”、“errors”和“RX bytes”。

    编辑:

    所以:

    以我的方式获取这些数据真的不安全吗?

    不是真的。您只需要记住,您的软件依赖于某些第三方软件的输出字符串,这些软件有些超出您的控制范围,并且将来可能会发生变化。这将是你的定期测试和维护工作,没什么可悲的,这就是软件的生命。

    如果是,正确的做法是什么?

    再次,“不”,但如果您想对此做到无懈可击:不要依赖第三方软件的文本输出。这通常涉及编写您的自己的代码来替换这些工具,这可能是一项艰巨的任务。如果这样做,您会使用一些第三方库,好吧,库 API 也会随着时间而变化...... :-)

    编辑 2:

    在你的情况下,不依赖于iw 的输出(即编写你自己的“mini iw”),并考虑到你想用 Python 编码:

    在低级别iw,用 C 编写,使用 libnl(也在 C 中)与内核通信以获取信息/在网络接口上执行操作。

    https://www.infradead.org/~tgr/libnl/

    你很幸运:似乎有一个积极维护的 Python libnl 库版本。

    https://pypi.python.org/pypi/libnl/0.2.0

    所以计划是:

    1. 研究 iw C 源代码以了解 netlink/libnl 它执行的操作以获取/设置您感兴趣的部分。
    2. 在您的代码中使用 Python libnl 来复制它。

    (请注意,libnl/netlink 被设计为一种非常通用的、长期可扩展的机制。它的设计目的确实是为了取代 ad-hoc ioctl。这种通用性带来了一定的复杂性:它可以相当复杂/涉及大量编码才能执行甚至简单的任务。)

    正如我在上面写的那样,编写自己的代码来替换工具可能是一项艰巨的任务。对命令的输出进行 grep 编码只需几分钟即可编写代码,而在这里这可能需要数天或数周的工作。所以你必须在“快速简单但不那么干净”和“独立、干净、可扩展但昂贵”之间做出选择。这取决于:您是否致力于生产工业级、客户支持的软件,它是公司内部工具,还是只是一个周末的业余爱好软件项目。

    【讨论】:

      【解决方案2】:

      我不知道是否适用于覆盆子,但使用@jbm 提到的途径,我浏览了 netlink 和 ioctl 教程并开发了 PyRIC (https://github.com/wraith-wireless/PyRIC),它完全是 Python,没有子进程,iw 输出解析等。你问它很简单

      pyw.interfaces() # get all system interfaces
      => ['lo','eth0','wlan']
      
      pyw.winterfaces() # get all system wireless interfaces
      => ['wlan0']
      

      如果您作为开发人员检查一下,我将不胜感激。

      【讨论】:

        猜你喜欢
        • 2016-01-02
        • 1970-01-01
        • 2021-05-11
        • 1970-01-01
        • 2014-02-10
        • 1970-01-01
        • 1970-01-01
        • 2016-09-15
        • 2017-06-02
        相关资源
        最近更新 更多