Как экземпляр Linux определяет свой IP-адрес?
То есть не 127.0.0.1.
Сохраняется ли это в файле или ifconfig каким-то образом вычисляет это при каждом вызове?
Мне удалось решить эту задачу, просто чтобы показать, что я приложил усилия, но это не то, что я бы включил в серьезное приложение:
sudo ifconfig | head -n 2 | tail -n 1 | tr -s " " | tr " " ":" | cut -d":" -f 4
решение1
В вашем вопросе есть фундаментальные недостатки. Во-первых, хосты могут (и, скорее всего, будут) иметь более одного адреса (например, несколько интерфейсов) и даже более одного адреса на интерфейс. Это еще большая проблема с IPv6, где каждый глобально подключенный хост как минимумдваадреса.
Во-вторых, «лучший» способ сделать это из оболочки будет отличаться от системы к системе.
Линукс:
/sbin/ip addr show eth0 | awk -F"[ /]+" '/inet / {print $3}'
>= Солярис 11:
ipadm show-addr net0/v4 | awk -F"[ /]+" '/ok/ {print $5}'
Mac OS X/Darwin:
ipconfig getifaddr en0
Даже переход к наименьшему общему знаменателю и использование ifconfig
не будет согласованным, поскольку формат вывода может измениться. Однако, чтобы очистить ваш пример, используйте это:
ifconfig eth0 | awk -F"[ :]+" '/inet / {print $4}'
Если вы используете более сложный язык, например perl, ruby, java и т. д., вместо оболочки, каждый язык будет иметь свой собственный способ получения этих данных из ядра. Я оставлю поиск этого на ваше усмотрение.
решение2
Информация может измениться в любой момент, поэтому ее необходимо извлекать из ядра, ее нельзя сохранить в файле.
Нет действительно хорошего способа получить эту информацию. Ваш парсинг так же хорош, как и любой другой, за исключением того, что жесткое кодирование второй строки неверно: нет гарантии, что интерфейсы будут перечислены в каком-то определенном порядке. Довольно часто машина имеет более одного интерфейса: у вас может быть несколько сетевых карт или виртуальных интерфейсов.
Часто IP-адрес, который вас интересует, связан с маршрутом по умолчанию. В большинстве конфигураций вы можете получить нужный интерфейс с помощью команды route
, а затем извлечь IP-адрес этого интерфейса с помощью ifconfig
.
/sbin/ifconfig $(/sbin/route -n |
awk '$1 == "0.0.0.0" {print $8}') |
awk 'match($0, /inet addr:[.0-9]+/) {print substr($0, RSTART+10, RLENGTH-10)}'
Обратите внимание, что нет необходимости вызывать sudo
. ifconfig
и route
часто не используются по умолчанию PATH
для пользователей, не являющихся root, но вы можете использовать их без специальных привилегий, если вы только читаете информацию и не меняете настройки.
На вариантах unix, отличных от Linux, вам, возможно, придется подправить команды выше. Большинство из них имеют команды с именами ifconfig
и route
, но формат вывода может отличаться.
В Linux вместо ifconfig
и route
можно использовать ip
команду изiproute2набор инструментов. Хотя авторы iproute2 считают ifconfig
и route
устаревшими, на самом деле использование дает мало преимуществ ip
, поскольку вывод ip
не намного проще для анализа, а ifconfig
и route
всегда доступны, тогда как некоторые урезанные установки Linux не содержат ip
.
решение3
Все ответы здесь технически верны, но они не являются тем, что я бы считал "правильным" ответом. К сожалению, ваш вопрос крайне расплывчат (что я могу понять, если вы не очень хорошо разбираетесь в работе сетей в Linux), поэтому я дам несколько ответов на возможные интерпретации вопроса.
Основной IP-адрес машины
Машина имеет один IP выше всех остальных, который считается основным IP машины. Обратите внимание, что это довольно бессмысленно, так как у коробки может быть несколько IP, и какой из них будет использоваться, зависит от того (я расскажу об этом немного позже).
Основной IP — это просто IP, связанный с именем хоста машины. Вы можете узнать этот IP, выполнив следующее
getent hosts "$(hostname)" | awk '{ print $1 }'
Теперь, что делает эта команда, так это ищет IP для имени хоста машины в соответствии с /etc/nsswitch.conf
. В большинстве случаев /etc/nsswitch.conf
файл содержит hosts: files dns
. Это означает, что при попытке выполнить любой поиск имени хоста или адреса, он /etc/hosts
сначала будет искать, а затем консультироваться с DNS (как настроено в /etc/resolv.conf
).
Таким образом, команда, getent hosts "$(hostname)"
скорее всего, извлечет соответствующую запись из /etc/hosts
. awk
Просто извлекает только IP из этой строки.
( getent
это просто простая утилита для запроса «баз данных», перечисленных в /etc/nsswitch.conf
)
IP-адрес, используемый для связи с внешним миром
Как я уже упоминал ранее, основной IP машины не имеет особого значения. Машина может использовать любой из нескольких IP для связи. В вашем случае у вас, скорее всего, есть только один интерфейс и один (нелокальный) IP. Однако сервер может иметь несколько интерфейсов или IP (иногда несколько IP на одном интерфейсе).
Какой IP будет использоваться, определяется таблицей маршрутизации ядра. Я не буду вдаваться в подробности того, как работает таблица маршрутизации, поскольку это непросто (есть несколько таблиц маршрутизации, и какая из них будет использоваться, зависит от правил выбора таблицы). Я просто расскажу вам, как узнать, какой IP будет использоваться.
Чтобы узнать, какой IP-адрес будет использоваться для связи с определенным пунктом назначения, используйте следующую команду:
ip route get 1.2.3.4
(при этом 1.2.3.4
IP-адрес будет местом назначения)
На моем компьютере, если я сделаю это с одним из IP-адресов google.com ( 74.125.139.102
), я получу следующее:
74.125.139.102 via 192.168.0.1 dev wlan0 src 192.168.0.24
cache
Это говорит мне о том, что IP-адрес 192.168.0.24
будет использоваться всякий раз, когда мой компьютер будет подключаться к 74.125.139.102
.
Если вам нужен только IP, вы можете просто добавить дополнительный адрес grep
в конце.
ip route get 1.2.3.4 | grep -oP '(?<=src )\S+'
grep
используется вместо , awk
потому что он менее подвержен ошибкам. Возможно, строка может измениться, и IP не будет в том же месте, но он всегда будет следовать за "src", поэтому мы просто берем значение сразу после "src"
IP-адрес шлюза по умолчанию
Наконец, есть шлюз по умолчанию. Если у вас нет определенного пункта назначения для запроса, чтобы узнать, какой IP будет использоваться, вы можете выбрать тот, что есть в шлюзе по умолчанию. Если у вас только один интерфейс, это все, что будет иметь значение в любом случае.
По сути, это то же самое, что и выше, только в качестве пункта назначения для поиска используется шлюз по умолчанию.
ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')"
Это даст вам строку, похожую на ту, что в разделе выше. Значение src
— это IP, который будет использоваться для трафика, проходящего через шлюз по умолчанию.
Как и в предыдущем разделе, чтобы получить только IP, добавьте grep
.
ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')" | grep -oP '(?<=src )\S+'
решение4
Ваш запрос неоднозначен, обычно под словом «localhost» подразумевают интерфейс loopback, а 127.0.0.1 — наиболее распространенный и правильный ответ.
Чего вам не хватает, так это:
- тот факт, что каждый интерфейс может иметь свой IP-адрес, интерфейс обратной связи является сетевым интерфейсом, таким же, как ваша сетевая карта Ethernet или беспроводной USB-приемник.
- как следствие, у одного ПК нет единого IP-адреса, все зависит от того, какой интерфейс вы рассматриваете и сколько интерфейсов вы используете в своей ОС.
Вас, вероятно, заинтересует тема «Таблицы маршрутизации ядра», которая является хорошим способом начать понимать, как ядро обрабатывает вашу сетевую активность.