Как получить мой собственный IP-адрес и сохранить его к переменной в сценарии оболочки?

С host от dnsutils пакета:

$ host unix.stackexchange.com
unix.stackexchange.com has address 64.34.119.12

(Исправленное имя пакета согласно комментариям. Как примечание другие дистрибутивы имеют host в различных пакетах: bind9-хост Debian/Ubuntu, openSUSE связывает-utils, Frugalware связывают.)

67
12.02.2012, 18:21
22 ответа

Не настолько легко, если Вы хотите принять во внимание wlan и другие альтернативные интерфейсы. Если Вы знаете, для какого интерфейса Вы хотите адрес (например, eth0, первая плата Ethernet), можно использовать это:

ip="$(ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"

Другими словами, получите меня информация о конфигурации сети, ищите eth0, получите ту строку и следующую (-A 1), получите только последнюю строку, получите вторую часть той строки при разделении с :, затем получите первую часть этого при разделении с пространством.

31
27.01.2020, 19:31
  • 1
    я добавил дополнительное grep к Вашему коду для игнорирования любого интерфейса с "eth0": в нем; это теперь работает, как я ожидаю (предоставление только "eth0" IP-адреса и не любых подынтерфейсов (eth0:0, eth0:1, и т.д.): ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)" –   12.02.2013, 21:49
  • 2
    Можно пропустить первый grep при помощи ifconfig eth0 –  Bryan Larsen 01.12.2014, 18:29
  • 3
    ifconfig удерживается от использования, необходимо использовать ip address вместо этого –  alexises 23.12.2015, 17:42

Я полагаю, что "современные инструменты" способ получить Ваш адрес ipv4 должны проанализировать 'IP', а не 'ifconfig', таким образом, это было бы что-то как:

ip4=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
ip6=$(/sbin/ip -o -6 addr list eth0 | awk '{print $4}' | cut -d/ -f1)

или что-то как этот.

70
27.01.2020, 19:31
  • 1
    ip доступно на всем Red Hat и дистрибутивах Fedora, которые я использовал. ip часть iproute2 пакета (linuxfoundation.org/collaborate/workgroups/networking/iproute2). ifconfig и route предположительно, удерживаются от использования, хотя они продолжают использоваться большим количеством людей, особенно в сценариях. ip намного более parsable, в моем opionion. –  jsbillings 03.03.2011, 17:13
  • 2
    ip также доступно на всем Debian, и Debian основывал дистрибутивы, которые я видел. Это - часть iproute пакета, который отмечен как важный. –  Arrowmaster 04.03.2011, 01:43
  • 3
    Это абсолютно, как это должно быть сделано, я был бы downvote другие ответы для их использования ifconfig. ip часть iproute2 пакета, который является многими дистрибутивами по умолчанию. Это находится в самом хорошем repos к. en.wikipedia.org/wiki/Iproute2 –  jwbensley 15.09.2012, 15:13
  • 4
    @jsbillings Почему /sbin/ip вместо ip? –  l0b0 15.01.2013, 15:02
  • 5
    Это - превосходный ответ! Комбинация awk и cut мягко забавно для меня, вот возможная альтернатива, которая не может на самом деле быть лучше: ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }' –  Swiss 16.06.2017, 00:21

Я использую эту остроту:

IP=$(/sbin/ifconfig | grep -e "inet:" -e "addr:" | grep -v "inet6" | grep -v "127.0.0.1" | head -n 1 | awk '{print $2}' | cut -c6-)

Использование ifconfig (широко доступный), не берет localhost обратитесь, не связывайте Вас с данным именем интерфейса, не принимайте во внимание IPv6, и пытается получить IP первого доступного сетевого интерфейса.

1
27.01.2020, 19:31

Почему не просто делают IP=$(hostname -I) ?

34
27.01.2020, 19:31
  • 1
    hostname -i дает мне просто 127.0.0.1, hostname -I дает мне корректный Адрес IP... –  student 15.09.2012, 15:41
  • 2
    @student да действительно, я протестировал его на машине, которая имеет, может разрешить ее имя хоста, как говорится в странице справочника -i Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option; use hostname --all-ip-addresses –  Andrei 15.09.2012, 15:49
  • 3
    Как я могу настроить свою машину для разрешения ее имени хоста? –  student 15.09.2012, 15:58
  • 4
    самый легкий путь добавляет его к /etc/hosts, наряду с соответствующим IP-адресом –  Andrei 16.09.2012, 13:06
  • 5
    Нет -I на FreeBSD, но можно использовать dig +short `hostname -f` –  Tigger 03.06.2015, 03:07

Зависит, что Вы подразумеваете под собственным IP-адресом. Системы имеют IP-адреса на нескольких подсетях (иногда несколько на подсеть), часть из который IPv4, некоторый IPv6 с помощью устройств как адаптеры Ethernet, петлевые интерфейсы, туннели VPN, мосты, виртуальные интерфейсы...

Я Вы имеете в виду IP-адрес, которым другое данное устройство может достигнуть Вашего компьютера, необходимо узнать, какая подсеть то есть, и о какой версии IP мы говорим. Кроме того, примите во внимание, что из-за NAT, выполненного брандмауэром/маршрутизаторами, IP-адрес интерфейса не может совпасть с удаленным хостом, видит входящее соединение от Вашего компьютера, прибывающего из.

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

Для IPv4 (вероятно, работает на IPv6 также), прием, который работает во многих нельдах включая Linux для обнаружения, IP-адрес интерфейса, используемого для достижения данного хоста, состоит в том, чтобы использовать подключение (2) на сокете UDP и использовать getsockname ():

Например, на моем домашнем компьютере:

perl -MSocket -le 'socket(S, PF_INET, SOCK_DGRAM, getprotobyname("udp"));
connect(S, sockaddr_in(1, inet_aton("8.8.8.8")));
print inet_ntoa((sockaddr_in(getsockname(S)))[1]);'

Использовался бы для обнаружения IP-адреса интерфейса, через который я достигну 8.8.8.8 (сервер DNS Google). Это возвратило бы что-то как "192.168.1.123", который является адресом интерфейса для маршрута по умолчанию к Интернету. Однако Google не видел бы запрос DNS от моей машины как прибывающий из того IP-адреса, который является частным, поскольку существует NAT, выполненный моим домашним широкополосным маршрутизатором.

подключение () на сокете UDP не отправляет пакета (UDP без установления соединения), но готовит сокет путем запросов таблицы маршрутизации.

7
27.01.2020, 19:31

Если Вы хотите адрес интерфейса, самый легкий путь состоит в том, чтобы установить moreutils затем:

anthony@Zia:~$ ifdata -pa br0
172.16.1.244

ifdata ответы в значительной степени каждый вопрос Вы испытали бы желание проанализировать ifconfig вывод для.

Если Вы хотите узнать свой IP-адрес, поскольку внешняя сторона видит его (вне любого NAT, и т.д.), существует много сервисов, это сделает это. Каждый довольно легок:

anthony@Zia:~$ curl ifconfig.me
173.167.51.137
26
27.01.2020, 19:31
  • 1
    , О, совершенство, спасибо за этот ответ. Никогда не слышал о moreutils прежде. Я серьезно полагал, что запись моей собственной небольшой программы C сделала точно это. –  Chris Harrington 28.02.2016, 04:02
  • 2
    Было бы хорошо иметь ifdata добавленный в iproute2. Возможно, новый названный двоичный файл ipdata –  Swiss 16.06.2017, 00:25
  • 3
    ifdata хорош, НО он не делает поддержек ipv6. –  BringBackCommodore64 06.07.2017, 14:29

Мне нужно было сделать это в псевдониме, чтобы начать радиосервер в моем проводном NIC. Я использовал

ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
0
27.01.2020, 19:31

На FreeBSD можно использовать

dig +short `hostname -f`

Это может работать для других сред, зависит от настройки.

-121--6178-

Чтобы получить адреса IPv4 и IPv6, не предполагая, что основным интерфейсом является eth0 (в настоящее время em1 встречается чаще ), попробуйте:

ips=$(ip -o addr show up primary scope global |
      while read -r num dev fam addr rest; do echo ${addr%/*}; done)
  • -o использует формат вывода в одну строку, который проще обрабатывать с помощью read , grep и т. д.
  • up исключает устройства, которые не являются активными
  • scope global исключает частные/локальные адреса, такие как 127,0,0,1 и fe80:Предварительные выборы:/64
  • исключают временные адреса (предположение, что вы хотите адрес, который не изменяется)
15
27.01.2020, 19:31

Во FreeBSD вы можете использовать

dig +short `hostname -f`

Это может работать в других средах, в зависимости от ваших настроек.

2
27.01.2020, 19:31

Некоторые команды работают на centos 6 или 7, приведенная ниже команда работает на обоих:

#!/bin/sh

serverip=`/sbin/ifconfig eth0 | grep "inet" | awk '{print $2}' | awk 'NR==1' | cut -d':' -f2`

echo $serverip
0
27.01.2020, 19:31
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

ipa=$(hostname -i|cut -f2 -d ' ')
8
27.01.2020, 19:31

Предполагая что у вас могут быть разные интерфейсы с разными именами , но , что вам нужен первый не-localhost и не-ipv6, вы можете попробовать:

ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
2
27.01.2020, 19:31

Я замечаю, что вы используете ключ DSA. OpenSSH 7.0 и выше по умолчанию отключена поддержка ключей DSA. Можно проверить, вызывает ли это проблемы. См. SSH продолжает пропускать мой лобовый ключ и запрашивать пароль и https://superuser.com/q/1016989/93541 .

-121--228579-
awk 'NF==3' file

Печать строки, если число полей равно 3. Довольно просто изменить количество столбцов в соответствии с вашими данными.

Однако, как было указано, это не работает с требованием ОП о переменном количестве полей.

-121--66780-
hostname -I >> file_name 

это сделает все, что вы хотите

-2
27.01.2020, 19:31

Предполагая, что вам нужен ваш основной общедоступный IP-адрес в том виде, в каком он виден остальному миру , попробуйте любой из этих:

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
1
27.01.2020, 19:31

Этот фрагмент избегает жесткого -кодирования имени устройства (типа eth0 )и будет использовать ipвместоifconfig:

/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/'

Он вернет IP-адрес первого активного устройства, указанного в выводе ip addr. В зависимости от вашей машины это может быть адрес ipv4 или ipv6.

Чтобы сохранить его в переменной, используйте:

ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/')
-1
27.01.2020, 19:31
myip=$(curl -kLs "http://api.ipify.org")

или

myip=$(wget -q "http://api.ipify.org" -O -)
0
27.01.2020, 19:31

все решения, использующие awk/sed/grep, кажутся слишком сложными и уродливыми для моей ситуации... поэтому я придумал это действительно простое решение, НО будьте осторожны, потому что оно делает некоторые предположения, а именно предположение, что ПОСЛЕДНИЙ интерфейс является единственным тебе это интересно. если вы согласны с этим, то это довольно чисто:

ifconfig | awk '/net / { x = $2 } END { print x }'

в противном случае вы могли бы сделать какой-нибудь глупый оператор ifдля проверки определенного префикса или любого другого критерия, который у вас может быть.

0
27.01.2020, 19:31

Простая команда для уточнения IP-адреса с интерфейсом по умолчанию.

ip route | grep src | awk '{print $NF; exit}'

Протестировано на всех ОС Unix

1
27.01.2020, 19:31

Вы должны использоватьip(вместо ifconfig), так как он актуален, поддерживается и, возможно, наиболее важно для целей написания сценариев, он дает согласованный и разборчивый вывод. Ниже приведены несколько подобных подходов :

.

Если вам нужен адрес IPv4 для вашего интерфейса Etherneteth0:

$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24  

Как сценарий:

$ INTFC=eth0  
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}') 
$ echo $MYIPV4
192.168.1.166/24

Результат, полученный выше, представлен в нотации CIDR. Если нотация CIDR не нужна, ее можно удалить:

$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1 
192.168.1.166  

Другой вариант, который ИМХО является «наиболее элегантным», — получение адреса IPv4 для любого интерфейса, используемого для подключения к указанному удаленному хосту (8.8.8.8 в данном случае ). Предоставлено @gatoatigrado в этот ответ:

$ ip route get 8.8.8.8 | awk '{ print $NF; exit }'
192.168.1.166

Как сценарий:

$ RHOST=8.8.8.8  
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166

Это прекрасно работает на хосте с одним интерфейсом, но более предпочтительно будет также работать на хостах с несколькими интерфейсами и/или спецификациями маршрута.

ipбыл бы моим предпочтительным подходом, но это, конечно, не единственный способ освежевать эту кошку. Вот еще один подход, который использует hostname, если вы предпочитаете что-то более простое/краткое:

$ hostname --all-ip-addresses | awk '{print $1}'  

Или, если вам нужен адрес IPv6:

$ hostname --all-ip-addresses | awk '{print $2}'  
0
27.01.2020, 19:31

Если вы ищете общедоступный IP-адрес ящика , вы можете использовать следующее:

  • dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \"

Вы можете использовать опции dig(1), такие как -4или -6, чтобы специально искать IPv4 или IPv6-адрес; Google предоставит ответ в виде записи типа TXT, которая будет заключена в кавычки при представлении dig;если вы хотите впоследствии использовать переменную с такими утилитами, как traceroute, вы должны использовать что-то вроде tr (1 ), чтобы удалить указанные кавычки.

Другие варианты включают whoami.akamai.netи myip.opendns.com, которые отвечают с Aи AAAAзаписывают (вместо TXT, как в приведенном выше примере от Google ), поэтому они не требуют удаления кавычек:

  • dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short

  • dig -4 @resolver1.opendns.com -t any myip.opendns.com +short

  • dig -6 @resolver1.opendns.com -t any myip.opendns.com +short

Вот пример скрипта, в котором используются все указанные выше параметры для установки переменных:

#!/bin/sh
IPANY="$(dig @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv4="$(dig -4 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
GOOGv6="$(dig -6 @ns1.google.com -t txt o-o.myaddr.l.google.com +short | tr -d \")"
AKAMv4="$(dig -4 @ns1-1.akamaitech.net -t a whoami.akamai.net +short)"
CSCOv4="$(dig -4 @resolver1.opendns.com -t a myip.opendns.com +short)"
CSCOv6="$(dig -6 @resolver1.opendns.com -t aaaa myip.opendns.com +short)"
printf '$GOOG:\t%s\t%s\t%s\n' "${IPANY}" "${GOOGv4}" "${GOOGv6}"
printf '$AKAM:\t%s\n$CSCO:\t%s\t%s\n' "${AKAMv4}" "${CSCOv4}" "${CSCOv6}"

Если вы ищете частный IP-адрес или набор всех IP-адресов, назначенных ящику, вы можете использовать некоторую комбинациюifconfig(в BSD и GNU/Linux ),ip addr(в GNU/Linux ),hostname(опции -iи -Iв GNU/Linux )и netstat, чтобы узнать, что происходит.

1
27.01.2020, 19:31

Возможно, это не самое надежное и правильное решение, но, в отличие от большинства других решений, эта команда работает как на Linux, так и на Mac (BSD ).

host `hostname` | awk '{print $NF}'
-1
27.01.2020, 19:31

Это напечатает IP-адрес соединения, которое в настоящее время UP:

ip -4 -j a | jq -r '.[] | select(.operstate=="UP") |.addr_info[].local'

ip -4 -j a-показывать адреса IPv4 в формате JSON

jq -r '.[] | select(.operstate=="UP") |.addr_info[].local'-найти объект, который имеет "operstate": "UP", и получить localзначение свойства (, которое находится в массиве addr_info).

Флаг -rдля jqозначает «показывать исходный вывод».

0
04.04.2021, 20:54

Теги

Похожие вопросы