对于一些隧道和绑定脚本,我需要找到一个(任何)本地(非环回)实际以太网链路接口及其 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
:还有其他的吗?ip
ethtool
netstat
答案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\b
else执行 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