Como obter meu próprio endereço IP e salvá-lo em uma variável em um script de shell?

56

Como posso obter meu próprio endereço IP e salvá-lo em uma variável em um script de shell?

    
por Tom Brito 03.03.2011 / 14:17

18 respostas

29

Não é tão fácil se você quiser levar em conta o wlan e outras interfaces alternativas. Se você sabe para qual interface deseja o endereço (por exemplo, eth0, a primeira placa Ethernet), você pode usar isto:

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

Em outras palavras, obtenha as informações de configuração de rede, procure por eth0 , obtenha essa linha e a próxima ( -A 1 ), obtenha somente a última linha, obtenha a segunda parte dessa linha ao dividir com : , depois obtenha a primeira parte disso ao dividir o espaço.

    
por 03.03.2011 / 14:24
60

Eu acredito que a maneira das "ferramentas modernas" de obter o seu endereço ipv4 é analisar o 'ip' em vez do 'ifconfig', então seria algo como:

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)

ou algo parecido.

    
por 03.03.2011 / 14:52
29

Por que não simplesmente IP=$(hostname -I) ?

    
por 15.09.2012 / 12:20
20

Se você quiser o endereço de uma interface, a maneira mais fácil é instalar moreutils então:

anthony@Zia:~$ ifdata -pa br0
172.16.1.244

ifdata responde a praticamente todas as perguntas que você seria tentado a analisar ifconfig output para.

Se você quiser descobrir seu endereço IP como o lado externo o vê (além de qualquer NAT etc.), há muitos serviços que farão isso. Um é bastante fácil:

anthony@Zia:~$ curl ifconfig.me
173.167.51.137
    
por 24.07.2013 / 16:38
10

Para obter endereços IPv4 e IPv6 e não assumir que a interface principal é eth0 (atualmente, em1 é mais comum ), tente:

ips=$(ip -o addr show up primary scope global |
      while read -r num dev fam addr rest; do echo ${addr%/*}; done)
  • -o usa o formato de saída de uma linha, que é mais fácil de processar com read , grep , etc.
  • up exclui dispositivos que não estão ativos
  • scope global exclui endereços privados / locais, como 127.0.0.1 e fe80::/64
  • primary exclui endereços temporários (supondo que você queira um endereço que não seja alterado)
por 03.06.2015 / 02:27
7
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$//g')

ipa=$(hostname -i|cut -f2 -d ' ')
    
por 17.09.2015 / 23:45
6

Eu não quero ser um idiota, mas existe um jeito correto e é isso. Você ajusta a saída de ip route para obter apenas o IP de origem. Dependendo do IP que você está tentando acessar, "meu próprio endereço IP" (palavras do OP) será diferente. Se você se preocupa em acessar a Internet pública, o uso do servidor DNS do Google 8.8.8.8 é bastante normal. Então ...

A resposta curta é:

ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'

Aqui está a explicação detalhada

Se eu quiser que o ip que eu uso para acessar a internet , eu uso isso:

pi@et3:~ $ ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'
10.55.0.200

Se eu quiser que o ip que eu uso para alcançar algo na minha VPN , eu uso isso:

pi@et3:~ $ ip route get 172.31.0.100 | sed -n '/src/{s/.*src *//p;q}'
172.29.0.9

This next one is really just for illustrative purposes. But, it should work on any Linux system. So, you can use this to demonstrate that, yes, all machines have multiple IP addresses at all times.

Se eu quisesse que o ip eu usasse para eu mesmo , eu usaria isso:

pi@et3:~ $ my_ip=$(getent hosts $(cat /etc/hostname) | awk '{print $1; exit}')
pi@et3:~ $ ip route get $my_ip | sed -n '/src/{s/.*src *//p;q}'
127.0.0.1

Mais sobre esse comando sed

Primeiro, deixe-me dizer que, ao escolher ferramentas unix, você tenta escolher as ferramentas que exigem o menor número de tubos. Assim, enquanto algumas respostas canalizam ifconfig para grep para sed para head , isso raramente é necessário. Quando você vê, deve levantar uma bandeira vermelha que você está tomando conselhos de alguém com pouca experiência. Isso não torna a "solução" errada. Mas, provavelmente, poderia usar alguma otimização.

Eu escolhi sed porque é mais concisa do que o mesmo fluxo de trabalho em awk . Eu não acho que qualquer outra ferramenta além dessas 2 seria apropriada.

Vamos examinar o que o sed -n '/src/{s/.*src *//p;q}' faz:

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/.*src *//    # regex match "anything followed by 'src' followed by any number of spaces" and replace it with "nothing"
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

Mais sobre minha rede

Meu ifconfig mostra que tenho tun0 para minha VPN e eth0 para minha lan.

pi@et3:~ $ 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)
    
por 02.11.2017 / 22:09
5

Depende do que você quer dizer com o próprio endereço IP. Os sistemas têm endereços IP em várias sub-redes (às vezes vários por sub-rede), alguns dos quais IPv4, alguns IPv6 usando dispositivos como adaptadores ethernet, interfaces de loopback, túneis VPN, pontes, interfaces virtuais ...

Eu quero dizer o endereço IP pelo qual outro determinado dispositivo pode acessar seu computador, você precisa descobrir qual sub-rede é essa e de qual versão do IP estamos falando. Além disso, lembre-se de que, por causa do NAT realizado por firewall / roteadores, o endereço IP de uma interface pode não ser o mesmo que um host remoto vê uma conexão de entrada vinda do seu computador.

Quando há roteamento de fonte sofisticada ou roteamento por protocolo / porta, pode ser difícil descobrir qual interface seria usada para falar com um computador remoto em um determinado protocolo e, mesmo assim, não há garantia de que o endereço IP desse A interface pode ser endereçada diretamente pelo computador remoto que deseja estabelecer uma nova conexão com o computador.

Para o IPv4 (provavelmente funciona também para IPv6), um truque que funciona em muitos unices, incluindo o Linux, para descobrir o endereço IP da interface usada para acessar um determinado host é usar um connect (2) em um soquete UDP. e use o getsockname ():

Por exemplo, no meu computador doméstico:

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]);'

Seria usado para descobrir o endereço IP da interface através da qual eu alcançaria o 8.8.8.8 (servidor DNS do google). Ele retornaria algo como "192.168.1.123", que é o endereço da interface da rota padrão para a Internet. No entanto, o Google não veria uma solicitação de DNS da minha máquina como proveniente desse endereço IP, que é particular, já que o NAT é executado pelo meu roteador doméstico de banda larga.

connect () em um soquete UDP não envia nenhum pacote (o UDP é sem conexão), mas prepara o soquete consultando a tabela de roteamento.

    
por 16.09.2012 / 12:39
2

No FreeBSD você pode usar

dig +short 'hostname -f'

Isso pode funcionar para outros ambientes, depende da sua configuração.

    
por 03.06.2015 / 02:09
1

Eu uso este verso:

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-)

Usa ifconfig (amplamente disponível), não aceita localhost endereço, não o vincula a um determinado nome de interface, não leva em consideração o IPv6 e tenta obter o IP da primeira interface de rede disponível. / p>     

por 04.03.2011 / 00:34
1

Assumindo que você pode ter várias interfaces de vários nomes mas que você deseja o primeiro não-localhost e não-ipv6, você pode tentar:

ip='ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1'
    
por 17.11.2015 / 17:35
0

Eu precisava fazer isso dentro de um alias para iniciar um servidor de rádio na minha placa de rede com fio. Eu usei

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

Alguns comandos estão trabalhando no centos 6 ou 7, o comando abaixo trabalhando em ambos,

#!/bin/sh

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

echo $serverip
    
por 06.08.2015 / 13:03
0

Supondo que você precisa do seu IP público principal como visto do resto do mundo , experimente qualquer um deles:

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
    
por 11.07.2017 / 08:19
0

Esse snippet evita codificar o nome do dispositivo (como 'eth0') e usará ip em vez de ifconfig :

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

Ele retornará o IP do primeiro dispositivo ativo listado na saída de ip addr . Dependendo da sua máquina, isso pode ser um endereço ipv4 ou ipv6.

Para armazená-lo em uma variável, use:

ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/')
    
por 07.08.2017 / 16:34
0
myip=$(curl -kLs "http://api.ipify.org")

ou

myip=$(wget -q "http://api.ipify.org" -O -)
    
por 07.08.2017 / 20:33
0

todas as soluções usando o awk / sed / grep parecem excessivamente complexas e feias para minha situação ... então eu criei uma solução muito simples, MAS tome cuidado, pois faz algumas suposições, a saber, a suposição de que a interface LAST é a única você está interessado. se você está bem com isso, então isso é muito limpo:

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

caso contrário, você poderia fazer alguma declaração if para testar um prefixo específico ou qualquer outro critério que você possa ter.

    
por 07.09.2017 / 18:24
-2
hostname -I >> file_name 

isso fará tudo o que você quiser

    
por 23.12.2015 / 07:53