返回真实本地以太网链路 IP 地址的最可靠脚本是什么

返回真实本地以太网链路 IP 地址的最可靠脚本是什么

对于一些隧道和绑定脚本,我需要找到一个(任何)本地(非环回)实际以太网链路接口及其 IP 地址。

笔记这是一个开发环境 - 在我的 Linux 笔记本电脑上 - 并且这个配置是动态的(可以是 Wifi、以太网等)

笔记我已经运行了大量 docker 和 kubernetes 子系统,因此有很多桥接器、虚拟接口等。

以下是我目前所掌握的信息:

nmcli可以给我wifi设备:

nmcli d  | grep wifi | cut -d ' ' -f 1

(但不是硬件链路本地以太网,因为 nmcli 报告的一些虚拟接口的类型也是“以太网”)

从这里我可以(a)躲过一些脆弱的 JQ

ip -br -j a show dev $DEV | jq -r .[1].addr_info[0].local

或者,xkcd://208我的成功之路?

ip -br a show dev $DEV | perl -nle 'print $1 if $_ =~ /.+ ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/'

注意事项:

  • ip有一个type过滤器,但没有用于实际硬件的过滤器
  • 我已经看过了、、、nmcli:还有其他的吗?ipethtoolnetstat

答案1

最近(~ 2017 年 11 月)iproute2工具提供-j[son]格式输出,正如您已经测试过的一样。与-d[etails]选项一起,在设计用于解析的输出中提供了大量信息。

看起来真实的接口不显示"linkinfo"对象(和相关的"info_kind"键,即接口的类型:韦特等。同样,如果没有 JSON 输出,这些接口就不会有其他每个虚拟接口(除了环回接口)所具有的以其类型开头的第三行:等等)。因此,仅测试是否"link_type": "ether"存在"linkinfo"应该只保留真正的以太网接口(Wifi 接口是其中的一部分)。当然也有限制:如果你创建一个mac80211_hwsim设备,它很可能看起来很真实,因为它模拟了一个设备(而不仅仅是一个界面)。

因此,使用您在问题中提到的专门的 JSON 处理工具:杰奇(阅读其jq 手册页面足以写出这个通用答案),我写了这个:

ip -details -json address show | \
    jq --join-output '.[] |
        if ."link_type" == "ether" and ."linkinfo" == null and (."addr_info" | length) > 0 then
            ."ifname" ,
            (."addr_info"[]|
                if ."family" == "inet" or ."family" == "inet6" then
                    " " + ."local"
                else
                    empty
                end), "\n"
        else
            empty
        end'

输出示例(已编辑):

 eth0 192.168.2.2 2001:db8:dead:beef:3116:312b:e620:3596 2001:db8:dead:beef:123:4567:89ab:cdef fe80::123:4567:89ab:cdef 
 wlan0 192.168.3.2 2001:db8:dead:bee5:dfa:a10b:df26:ef3e 2001:db8:dead:bee5:cdef:89ab:4567:123 fe80::cdef:89ab:4567:123 

笔记

  • 如果你想保留韦特接口(否则容器可能永远不会显示任何东西),您可以."linkinfo" == null用替换(."linkinfo" == null or ."linkinfo"."info_kind" == "veth")
  • 为了直观地读取命令的直接 JSON 输出,最好使用ip -details -pretty -json address show

答案2

ifconfig 以Say开头的ens3是接口。ip addr show ens3将显示该接口的所有信息。然后使用 grepinet过滤 ipaddresses。我猜你只想过滤掉 ipv4,然后使用inet\belse执行 grepinet6查找 ipv6 地址。要打印 ipaddress 字段,请执行awk '{print $2}'打印 inet 的第二部分的操作。

ip addr show ens3 | grep "inet\b" | awk '{print $2}' 

现在您有了带掩码的地址,如果您想丢弃掩码,则包括cut -d/ -f1将丢弃掩码部分。

ip addr show ens3 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1

将其放入 bash 脚本中并在需要时运行。

答案3

我无法在现有的实用程序中找到返回此信息的开关。

但事实证明,/sys/class/net/<iface>/device如果它是一个实际的硬件接口,该文件似乎存在。(我确信这可能是一个错误的断言)

下面是一个 Python 代码片段,使用此类条目通过正则表达式从配置的接口中取出 IP 地址sysfs

#!/usr/bin/env python3

import os
import re

for dev in os.listdir('/sys/class/net'):
    if os.path.isdir('/sys/class/net/' + dev + '/device'):
        try:
            print(re.search(' ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})', os.popen('ip -br a show dev ' + dev).read()).groups()[0])
        except:
            pass

[1]https://gist.github.com/robshep/5daea97bd9f438d69c3e23e3ad02c0bd

相关内容