Для некоторых сценариев туннелирования и привязки мне нужно найти (любой) локальный (без обратной связи) фактический интерфейс связи Ethernet и его IP-адрес.
Заметка это среда разработки - на моем ноутбуке с Linux - и эта конфигурация является динамической (может быть Wi-Fi, Ethernet и т. д.)
Заметка У меня работает множество подсистем docker и kubernetes, и, следовательно, есть много мостов, виртуальных интерфейсов и т. Д.
Вот что у меня есть на данный момент:
nmcli
может дать мне устройства Wi-Fi:
nmcli d | grep wifi | cut -d ' ' -f 1
(Но не аппаратный локальный Ethernet, так как тип, сообщаемый nmcli для некоторых виртуальных интерфейсов, также является ethernet)
От этого я мог (а) увернуться через какой-то хрупкий 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
фильтр, но не для реального hwnmcli
, ip
, ethtool
, netstat
: любые другие?Достаточно недавно (~ Ноя 2017) iproute2 инструменты обеспечивают -j[son]
формат вывода, как вы уже тестировали. Вместе с -d[etails]
вариант, в выводе, предназначенном для анализа, доступно много информации.
Похоже, что настоящие интерфейсы не отображают "linkinfo"
объект (и связанный "info_kind"
ключ, который является типом интерфейса: мост, vethи т. д. Точно так же без вывода JSON у этих интерфейсов нет третьей строки, которая есть у всех остальных виртуальных интерфейсов (хорошо, кроме loopback), которые начинаются со своего типа: мост и т.д.). Так что просто тестирование на "link_type": "ether"
и отсутствие "linkinfo"
должны сохранять только реальные интерфейсы Ethernet (частью которых являются интерфейсы Wi-Fi). Конечно, есть ограничения: если вы создадите mac80211_hwsim устройство, скорее всего, оно будет выглядеть реальным, поскольку оно имитирует устройство (а не просто интерфейс).
Итак, используя специализированный инструмент обработки JSON, который вы уже упоминали в своем вопросе: jq (читая его 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")
.ip -details -pretty -json address show
.Я не могу найти переключатель в существующей служебной программе, который возвращает это.
Но оказывается, что файл /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
Начать с ifconfig
Сказать ens3
это интерфейс. ip addr show ens3
покажет всю информацию для этого интерфейса. Затем выполните команду grep с помощью inet
фильтровать ip-адреса. Я думаю, вы хотите отфильтровать ipv4 только тогда, выполните команду grep с inet\b
еще inet6
для адреса 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 и запускайте, когда вам это нужно.