Узнать локальный IP-адрес/адреса на Arch Linux

Вопрос или проблема

До сих пор мои сетевые скрипты использовали hostname -i, но после недавнего обновления эта команда начала выдавать ошибку: hostname: gethostbyname: Unknown host.

Теперь я не знаю… стоит ли мне искать новую команду, такую как ip? Или это распространенная проблема? Я не могу найти упоминаний об этом нигде. Я бы использовал ip, но не могу понять, как отобразить два IP одновременно, например, когда оба интерфейса подключены (eth и wlp).

Какие-нибудь предложения?

То же самое случилось со мной сегодня. Я проверил/проверил контрольную сумму файла /usr/bin/hostname, он не изменялся недавно.

Я вывел информацию о открытых файлах из strace (исключая “No Such Files” в альтернативных $PATH):

$ strace hostname -i |& grep open | grep -v "No such file"
open("/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/hosts", O_RDONLY|O_CLOEXEC)  = 3
open("/usr/lib/libnss_mymachines.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/librt.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libnss_resolve.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 4

Поочередная проверка и сравнение с инкрементальными резервными копиями за последние несколько дней показало, что /etc/nsswitch.conf изменился с предыдущей версии от 30 сентября 2015 года на 10 декабря 2016 года.

Сравнение показывает различия (левая сторона предыдущая и восстановленная, правая сторона последняя и резервная):

$ diff -y /etc/nsswitch.conf /etc/nsswitch.conf.bck | grep \|
passwd: files                                                 | passwd: compat mymachines systemd
group: files                                                  | group: compat mymachines systemd
shadow: files                                                 | shadow: compat
hosts: files dns myhostname                                   | hosts: files mymachines resolve [!UNAVAIL=return] dns myhostn

Восстановление предыдущей версии /etc/nsswitch.conf решает проблему, и “hostname -i” снова возвращает IP-адреса, предоставленные интерфейсами, как обычно. Вы должны сделать резервную копию последней версии на всякий случай.

Обновление:
После того, как я сообщил о баге (https://bugs.archlinux.org/task/52133), сопровождающий пакета systemd Дейв Рейзнер указал, что проблема возникает только тогда, когда демон system-resolved не работает. Я проверил, и это верно. Чтобы новая версия /etc/nsswitch.conf работала:

systemctl enable systemd-resolved

необходима.

Согласно выводу “top” это добавляет размер резидентной памяти около 4мб. Альтернативно, можно продолжить с предыдущей строкой без systemd-resolved.

Если вы планируете использовать ip, вот пример, как получить правильный IP-адрес из вывода ip address show:

$ ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:92:55:ff brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 192.168.124.29/24 metric 1024 brd 192.168.124.255 scope global dynamic eth0
       valid_lft 2742sec preferred_lft 2742sec
    inet6 fe80::5054:ff:fe92:55ff/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever

Выполните:

ip a s dev eth0 | grep "inet " | grep -oE "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" | head -1

Объяснение:

  • ip a s dev eth0, что то же самое, что и ip address show dev eth0, выведет информацию только о устройстве eth0. Это устройство с необходимым мне IP-адресом. Вывод:
$ ip a s dev eth0

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:92:55:ff brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 192.168.124.29/24 metric 1024 brd 192.168.124.255 scope global dynamic eth0
       valid_lft 2331sec preferred_lft 2331sec
    inet6 fe80::5054:ff:fe92:55ff/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever

  • grep "inet " сопоставит строку, содержащую inet . Пробел здесь важен, чтобы избежать совпадения с inet6 (вы также можете использовать ip -4 a s dev eth0). Вывод:
$ ip a s dev eth0 | grep "inet "

    inet 192.168.124.29/24 metric 1024 brd 192.168.124.255 scope global dynamic eth0

  • grep -oE "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" — это регулярное выражение, которое сопоставит ТОЛЬКО строки, имеющие следующий вид: “(от 1 до 3 цифр)ТОЧКА(от 1 до 3 цифр)ТОЧКА(от 1 до 3 цифр)ТОЧКА(от 1 до 3 цифр)”.
    Шаблон регулярного выражения также можно сохранить в переменную и использовать позже:
    REGEX="[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}". Вывод:
$ REGEX="[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"
$ ip a s dev eth0 | grep "inet " | grep -oE $REGEX

192.168.124.29
192.168.124.255

  • head -1 выводит только первое совпадение (первую строку), которая идет сразу после init (вторая — это адрес broadcast). Вывод:
$ REGEX="[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"
$ ip a s dev eth0 | grep "inet " | grep -oE $REGEX | head -1

192.168.124.29

Если у вас есть доступ к hostname -I, просто используйте это:

hostname -I | cut -d' ' -f1

ip addr list eth0 | grep -Po "(?<=inet )[^/]+"

Не требует никакого разрешения DNS

.

Ответ или решение

Чтобы определить локальные IP-адреса на Arch Linux, стоит понимать, какие инструменты и команды доступны, и как ими эффективно пользоваться. Проблема с командой hostname -i, которая ранее выполняла эту задачу, может возникать из-за изменений в конфигурациях сети или системных обновлениях. В таком случае рекомендуется обратиться к более надежным инструментам, таким как команда ip.

Теория

В Linux для работы с сетевыми интерфейсами и получения информации о них используется утилита ip, входящая в пакет iproute2. Она предоставляет расширенные возможности по сравнению со старыми инструментами, такими как ifconfig. Команда ip может показать различные атрибуты сетевых интерфейсов, включая IP-адреса, с более высокой степенью детализации.

Пример

Рассмотрим базовый синтаксис команды для отображения IP-адресов всех интерфейсов:

ip addr show

Это даст полную информацию о каждом интерфейсе, включая IP-адреса, алиасы, состояния и характеристики. Однако если требуется извлечь только IP-адреса, без лишней информации, можно использовать комбинацию команд grep и awk для фильтрации и обработки вывода.

Применение

Чтобы получить IPv4-адреса всех активных интерфейсов, можно использовать следующую команду:

ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}'

Эта команда выводит только IPv4-адреса из всей информации, предоставляемой ip. Графическое выражение \d+(\.\d+){3} находит шаблоны, соответствующие четырем группам цифр, разделенных точками, что характерно для IPv4-адресов.

Если вы хотите получить IP-адрес для конкретного интерфейса, например eth0, команда будет следующей:

ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'

Данная команда сначала показывает информацию только для интерфейса eth0, а затем фильтрует вывод, чтобы показать только адреса IPv4.

Советы по устранению проблем

Если после обновлений возникли проблемы с hostname -i, причина может заключаться в изменении конфигурационных файлов, таких как /etc/nsswitch.conf. Этот файл управляет тем, как система решает различные запросы, включая запросы на получение IP-адресов хоста. Изучите изменения в этом файле и восстановите свои предыдущие настройки при необходимости.

Например, разница в конфигурации nsswitch.conf может быть следующей:

# Старый конфигурационный файл
hosts: files dns myhostname

# Новый конфигурационный файл
hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname

Если изменение в файле /etc/nsswitch.conf вызывает проблемы, вы можете восстановить старый файл или внести необходимые правки, чтобы обеспечить правильное разрешение IP-адресов.

Также стоит проверить состояние службы systemd-resolved, которая может влиять на процесс разрешения имен. Попробуйте включить и запустить её, если она отключена:

systemctl enable systemd-resolved
systemctl start systemd-resolved

В случае, если hostname -I доступен на вашей системе, его использование может значительно упростить задачу благодаря простоте синтаксиса:

hostname -I

Эта команда выведет все адреса, привязанные к интерфейсам без дополнительных настроек.

Заключение

Переход на ip для управления сетевыми интерфейсами в Arch Linux — это современный и правильный подход, особенно учитывая ограниченную поддержку старых инструментов и возможность появления ошибок после системных обновлений. Использование ip в сочетании с инструментами для обработки текста, такими как grep и awk, даёт гибкость и точность в получении необходимых данных о сети. И не забывайте регулярно проверять и поддерживать актуальность конфигурационных файлов, чтобы избежать неожиданных проблем.

Оцените материал
Добавить комментарий

Капча загружается...