Вопрос или проблема
До сих пор мои сетевые скрипты использовали 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
, даёт гибкость и точность в получении необходимых данных о сети. И не забывайте регулярно проверять и поддерживать актуальность конфигурационных файлов, чтобы избежать неожиданных проблем.