it-swarm-ru.tech

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

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

68
Tom Brito

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

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

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

31
l0b0

Я полагаю, что "современные инструменты" способ получить ваш адрес 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)

или что-то типа того.

71
jsbillings

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

39
Andrei

Если вам нужен адрес интерфейса, самый простой способ - установить moreutils:

[email protected]:~$ ifdata -pa br0
172.16.1.244

ifdata отвечает практически на все вопросы, для которых у вас возникнет искушение проанализировать вывод ifconfig.

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

[email protected]:~$ curl ifconfig.me
173.167.51.137
27
derobert

Чтобы получить адреса 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
  • primary исключает временные адреса (если вы хотите, чтобы адрес не менялся)
15
Mikel

Я не хочу быть придурком, но на самом деле путь справа - и все. Вы обрезаете вывод _ip route_, чтобы получить только исходный IP. В зависимости от того, какой IP-адрес вы пытаетесь получить, "мой собственный IP-адрес" (слова ОП) будет отличаться. Если вы хотите получить доступ к общедоступному Интернету, использование DNS-сервера Google 8.8.8.8 довольно стандартно. Так...

Краткий ответ:

_ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
_

Вот подробное объяснение

Если я хочу, чтобы ip, который я использую, достигал internet, я использую это:

_[email protected]:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
10.55.0.200
_

Если я хочу, чтобы ip, который я использую, достигал чего-то на моем VPN , я использую это:

_[email protected]:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
172.29.0.9
_

Этот следующий действительно только для иллюстративных целей. Но это должно работать на любой системе Linux. Таким образом, вы можете использовать это, чтобы продемонстрировать, что да, все машины имеют несколько IP-адресов в любое время.

Если бы я хотел использовать ip для достижения себя, я бы использовал это:

_[email protected]:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
[email protected]:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
127.0.0.1
_

Подробнее об этой команде sed

Прежде всего позвольте мне сказать, что при выборе инструментов Unix вы пытаетесь выбрать инструменты, которые требуют наименьшего количества каналов. Таким образом, хотя некоторые ответы будут перенаправлять ifconfig в grep в sed в head], это редко когда-либо необходимо. Когда вы видите это, это должно поднять красный флаг, что вы принимаете советы от кого-то с небольшим опытом. Это не делает "решение" неправильным. Но, возможно, оно может использовать некоторую оптимизацию.

Я выбрал sed, потому что он более краткий, чем тот же рабочий процесс в awk. (У меня есть пример awk ниже.) Я не думаю, что какой-либо другой инструмент, но эти 2 были бы уместны.

Давайте посмотрим, что делает sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}':

_sed            # the sed executable located via $PATH
-n             # no output unless explicitly requested
'              # begin the command space
/src/          # regex match the string 'src'
{              # begin a block of commands **
s/             # begin a substitution (match)
  .*src *      # match anything leading up to and including src and any number of spaces
  \([^ ]*\)    # define a group containing any number of non spaces
  .*           # match any trailing characters (which will begin with a space because of the previous rule).
/              # begin the substitution replacement
  \1           # reference the content in the first defined group
/              # end the substitution
p              # print (explicitly, remember) the result
;              # designate the end of the command
q              # quit
}              # end the block of commands
'              # end the command space

** all of which will be performed "on match"
  - otherwise only the first command to following the match would be performed "on match"
    - any other commands would be performed whether there was a match or not
_

Раньше я использовал _sed -n '/src/{s/.*src *//p;q}'_, но комментатор указал, что в некоторых системах есть конечные данные после поля src.

Использование awk

_ip route get 8.8.8.8 | \
    awk '{gsub(".*src",""); print $1; exit}'

# or

ip route get 8.8.8.8 | \
    awk '{for(i=1; i<NF; i++){if($i=="src"){i++; print $i; exit}}}'
_

Подробнее о моей сети

Мой ifconfig показывает, что у меня есть _tun0_ для моей VPN и _eth0_ для моей локальной сети.

_[email protected]:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.55.0.200  netmask 255.255.252.0  broadcast 10.55.3.255
        inet6 fe80::71e6:5d7c:5b4b:fb25  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:b2:96:84  txqueuelen 1000  (Ethernet)

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<Host>
        loop  txqueuelen 1  (Local Loopback)

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 172.29.0.9  netmask 255.255.255.255  destination 172.29.0.10
        inet6 fe80::3a8e:8195:b86c:c68c  prefixlen 64  scopeid 0x20<link>
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)

wlan0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:e7:c3:d1  txqueuelen 1000  (Ethernet)
_
9
Bruno Bronosky
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

ipa=$(hostname -i|cut -f2 -d ' ')
8
fastrizwaan

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

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

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

Для IPv4 (вероятно, работает и для IPv6), хитрость, которая работает во многих приложениях, включая Linux, для определения IP-адреса интерфейса, используемого для доступа к данному хосту, заключается в использовании connect (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).

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

8
Stéphane Chazelas

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

Dig +short `hostname -f`

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

2
Tigger

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

ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
2
Nicolas

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

Если вы хотите IPv4-адрес для вашего интерфейса Ethernet eth0:

$ 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  

Другой вариант, который IMHO является "наиболее элегантным", - это получение 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}'  
1
Seamus
myip=$(curl -kLs "http://api.ipify.org")

или

myip=$(wget -q "http://api.ipify.org" -O -)
1
Zibri

Я использую этот однострочник:

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
Andrea Spadaccini

Этот фрагмент позволяет избежать жесткого кодирования имени устройства (например, "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'/')
0
Philipp Claßen

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

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
0
Putnik

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

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

все решения, использующие awk/sed/grep, кажутся слишком сложными и уродливыми для моей ситуации ... поэтому я придумал это по-настоящему простое решение, но остерегайтесь, поскольку оно делает некоторые предположения, а именно предположение, что интерфейс LAST - это тот, который вы используете. интересно. если вы в порядке с этим, то это довольно чисто:

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

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

0
mad.meesh

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

Host `hostname` | awk '{print $NF}'
0
wisbucky

Некоторые команды работают с Centos 6 или 7, команда ниже работает на обоих,

#!/bin/sh

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

echo $serverip
0
lakshmikandan

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

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

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

0
M.S.Arun

Если вы ищете общедоступный 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 чтобы увидеть, что происходит.

0
cnst