¿Cómo obtener mi propia dirección IP y guardarla en una variable en un script de shell?

65

¿Cómo puedo obtener mi propia dirección IP y guardarla en una variable en un script de shell?

Tom Brito
fuente
2
Una advertencia: aquí hay muchas respuestas de "funciona en mi sistema" que pueden no ser portables en otros entornos. Tienes que decidir si quieres algo que funcione para ti o algo que se pueda compartir. Cada sistema tiene múltiples IP. Una solución portátil responde a la pregunta: "¿qué IP utilizo para llegar a bla ?" A funciona en mi solución de sistema responde la P: "¿cuál es mi IP?" con la A: "Creo que te refieres a este ..." Esto debería ser portátil unix.stackexchange.com/a/402160/9745
Bruno Bronosky
Esto proporciona una forma de obtener el formulario / proceso de dirección IP: unix.stackexchange.com/questions/365225/…
Pierz

Respuestas:

30

No es tan fácil si desea tener en cuenta wlan y otras interfaces alternativas. Si sabe para qué interfaz desea la dirección (por ejemplo, eth0, la primera tarjeta Ethernet), puede usar esto:

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

En otras palabras, consígueme la información de configuración de la red, busque eth0, obtenga esa línea y la siguiente ( -A 1), obtenga solo la última línea, obtenga la segunda parte de esa línea al dividir con :, luego obtenga la primera parte de eso al dividir con espacio

l0b0
fuente
1
Agregué un adicional grepa su código para ignorar cualquier interfaz con "eth0:" en él; esto ahora funciona como esperaba (dando solo la dirección IP "eth0" y no ninguna subinterfaz (eth0: 0, eth0: 1, etc.):ip="$(ifconfig | grep -v 'eth0:' | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1)"
66
Puede omitir el primer grep usandoifconfig eth0
Bryan Larsen
55
ifconfig está en desuso, debería usarlo ip addressen su lugar
alexises
70

Creo que la forma de "herramientas modernas" para obtener su dirección ipv4 es analizar 'ip' en lugar de 'ifconfig', por lo que sería algo así 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)

o algo así.

jsbillings
fuente
44
ipestá disponible en todas las distribuciones de Red Hat y Fedora que he usado. ipes parte del paquete iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfigy routesupuestamente están en desuso, aunque muchas personas continúan usándolas, especialmente en los guiones. ipes mucho más fácil de analizar, en mi opinión.
jsbillings
3
iptambién está disponible en todas las distribuciones basadas en Debian y Debian que he visto. Es parte del paquete iproute que está marcado como importante.
Arrowmaster
2
Así es absolutamente como debe hacerse, desestimaría las otras respuestas por su uso de ifconfig. ipes parte del paquete iproute2, que es una distribución por defecto. Está en la mayoría de los buenos repositorios. en.wikipedia.org/wiki/Iproute2
jwbensley
3
@jsbillings ¿Por qué en /sbin/iplugar de ip?
l0b0
1
Esta es una excelente respuesta! La combinación de awky cutes levemente divertida para mí, aquí hay una posible alternativa que en realidad puede no ser mejor:ip -o -4 addr show eth0 | awk '{ split($4, ip_addr, "/"); print ip_addr[1] }'
Swiss
32

¿Por qué no simplemente hacer IP=$(hostname -I)?

Andrei
fuente
3
hostname -ime da solo 127.0.0.1, hostname -Ime da la dirección IP correcta ...
estudiante
@student sí, de hecho, lo he probado en una máquina que puede resolver su nombre de host, como dice la página de manual-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
¿Cómo puedo configurar mi máquina para resolver su nombre de host?
estudiante
la forma más fácil es agregarlo /etc/hosts, junto con la dirección IP correspondiente
Andrei
3
No -Ien FreeBSD, pero puedes usarlodig +short `hostname -f`
Tigger
24

Si desea la dirección de una interfaz, la forma más fácil es instalar moreutils y luego:

anthony@Zia:~$ ifdata -pa br0
172.16.1.244

ifdataresponde casi todas las preguntas por las que te sentirías tentado a analizar la ifconfigsalida.

Si desea averiguar su dirección IP como la ve el exterior (más allá de cualquier NAT, etc.), hay muchos servicios que lo harán. Uno es bastante fácil:

anthony@Zia:~$ curl ifconfig.me
173.167.51.137
derobert
fuente
Oh Dios, gracias por esta respuesta. Nunca he oído hablar de moreutils antes. Estaba considerando seriamente escribir mi propio pequeño programa en C para hacer exactamente eso.
Chris Harrington
Sería bueno haber ifdataagregado iproute2. Tal vez un nuevo binario llamadoipdata
Swiss
ifdata es bueno PERO no es compatible con ipv6.
BringBackCommodore64
15

Para obtener direcciones IPv4 e IPv6, y no asumir que la interfaz principal es eth0(en estos días em1 es más común ), intente:

ips=$(ip -o addr show up primary scope global |
      while read -r num dev fam addr rest; do echo ${addr%/*}; done)
  • -outiliza el formato de salida de una línea, que es más fácil de procesar con read, grep, etc.
  • up excluye dispositivos que no están activos
  • scope globalexcluye direcciones privadas / locales como 127.0.0.1yfe80::/64
  • primaryexcluye direcciones temporales (suponiendo que desea una dirección que no cambie)
Mikel
fuente
1
Esta tiene que ser la mejor respuesta porque 1) no asume un nombre de dispositivo, 2) usa 'ip' en lugar de 'ifconfig' de la vieja escuela, y 3) también admite ipv6.
BringBackCommodore64
Acepté, es el mejor comienzo para la mayoría de los casos de uso. Puede pasar -4/ -6filtrar tipos de direcciones. También puede obtener fácilmente otros parámetros de la interfaz. Personalmente, no me gusta el bucle while y prefierogrep -o 'inet6\? [0-9a-f\.:]*' | cut -f 2 -d ' '
Jérôme Pouiller
7

Depende de lo que quiera decir con su propia dirección IP. Los sistemas tienen direcciones IP en varias subredes (a veces varias por subred), algunas de las cuales son IPv4, algunas IPv6 que utilizan dispositivos como adaptadores de Ethernet, interfaces de bucle invertido, túneles VPN, puentes, interfaces virtuales ...

Me refiero a la dirección IP por la cual otro dispositivo puede llegar a su computadora, debe averiguar qué subred es esa y qué versión de IP estamos hablando. Además, tenga en cuenta que debido a NAT realizada por firewall / enrutadores, la dirección IP de una interfaz puede no ser la misma que un host remoto ve una conexión entrante desde su computadora.

Cuando hay un enrutamiento de origen elegante o por enrutamiento de protocolo / puerto, puede ser difícil averiguar qué interfaz se usaría para hablar con una computadora remota a través de un protocolo dado e incluso entonces, no hay garantía de que la dirección IP de esa interfaz pueda ser directamente direccionable por la computadora remota que desea establecer una nueva conexión a su computadora.

Para IPv4 (probablemente también funciona para IPv6), un truco que funciona en muchos dispositivos, incluido Linux, para averiguar la dirección IP de la interfaz utilizada para llegar a un host determinado es usar una conexión (2) en un socket UDP y usar getsockname ():

Por ejemplo, en la computadora de mi casa:

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

Se utilizaría para averiguar la dirección IP de la interfaz a través de la cual llegaría a 8.8.8.8 (el servidor DNS de Google). Devolvería algo como "192.168.1.123", que es la dirección de la interfaz para la ruta predeterminada a Internet. Sin embargo, Google no vería que una solicitud de DNS de mi máquina provenga de esa dirección IP, que es privada, ya que el enrutador de banda ancha de mi casa realiza NAT.

connect () en un socket UDP no envía ningún paquete (UDP no tiene conexión), pero prepara el socket consultando la tabla de enrutamiento.

Stéphane Chazelas
fuente
7
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')

ipa=$(hostname -i|cut -f2 -d ' ')
fastrizwaan
fuente
1
Usar en -Ilugar de -ies mejor, ya que desearía ignorar las direcciones de bucle invertido, por lo que el comando final seríaipa=$(hostname -I|cut -f1 -d ' ')
Karl.S
1
Si grepno es suficiente, no lo canalices a otra cosa. Sólo tiene que utilizar la otra cosa ( sed, awk, etc.).
Bruno Bronosky
7

No quiero ser un imbécil, pero realmente hay una manera correcta y esta es. Recorta la salida de ip routepara obtener solo la IP de origen. Dependiendo de qué IP está tratando de alcanzar, "mi propia dirección IP" (palabras de OP) será diferente. Si te interesa llegar a Internet público, usar el servidor DNS 8.8.8.8 de Google es bastante estándar. Entonces...

La respuesta corta es:

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

Aquí está la explicación detallada.

Si quiero que la ip que uso llegue a internet , uso esto:

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

Si quiero que la ip que utilizo llegue a algo en mi VPN , uso esto:

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

El siguiente es realmente solo para fines ilustrativos. Pero, debería funcionar en cualquier sistema Linux. Por lo tanto, puede usar esto para demostrar que, sí, todas las máquinas tienen múltiples direcciones IP en todo momento.

Si quisiera que la ip que utilizo me alcance , usaría esto:

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 *\([^ ]*\).*/\1/p;q}'
127.0.0.1

Más sobre ese sedcomando

Primero permítanme decir que al elegir las herramientas de Unix, intentan elegir las herramientas que requieren la menor cantidad de tuberías. Así, mientras que algunas respuestas serán tubería ifconfiga grepa seda head, que es rara vez es necesario. Cuando lo vea, debería mostrar una señal de alerta de que está recibiendo consejos de alguien con poca experiencia. Eso no hace que la "solución" sea incorrecta. Pero, probablemente podría usar alguna racionalización.

Elegí sedporque es más breve que el mismo flujo de trabajo awk. (Lo he hecho desde un ejemplo awk a continuación.) No creo que haya ninguna otra herramienta, pero esas 2 serían apropiadas.

Examinemos qué sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'hace:

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
Nota:

Solía ​​usar, sed -n '/src/{s/.*src *//p;q}'pero un comentarista señaló que algunos sistemas tienen datos finales después del srccampo.

Usando 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}}}'

Más acerca de mi red

Mis ifconfigshows que tengo tun0para mi VPN y eth0para mi 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)
Bruno Bronosky
fuente
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *//p;q}'me dio 10.1.2.3 uid 1002. Entonces agrego agregar | awk '{print $1}'para mantener solo la dirección IP.
wisbucky
@wisbucky Nunca me canalizo sed / awk / grep entre sí en código grabado. (Lo usaré en la línea de comando cuando tenga prisa, pero nunca lo encontrará escrito en el disco que no sea en mi ~ / .bash_history) Actualicé la respuesta para usar awk y resuelve este problema.
Bruno Bronosky
1
@wisbucky No pude soportarlo. Hice que mi sed funcione con su entorno también.
Bruno Bronosky
2

En FreeBSD puedes usar

dig +short `hostname -f`

Esto puede funcionar para otros entornos, depende de su configuración.

Tigger
fuente
Creo que esto depende de la configuración /etc/resolv.confy de cómo el enrutador de red maneja los nombres de host locales. Está bien usar esto en su entorno si lo prueba y funciona. Pero si lo hace, está creando un sistema "frágil" que causará otros problemas si comparte esto. Usar con precaución.
Bruno Bronosky
2

Suponiendo que puede tener varias interfaces de varios nombres pero que desea la primera no localhost y no ipv6, puede intentar:

ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
Nicolas
fuente
ip = $ (ifconfig | grep -oP '(? <= inet addr:) \ S *' | grep -v 127)
rcjohnson el
1

Yo uso este one-liner:

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

Usos ifconfig(ampliamente disponible), no toma localhostdirección, no lo vincula a un nombre de interfaz dado, no tiene en cuenta IPv6 e intenta obtener la IP de la primera interfaz de red disponible.

Andrea Spadaccini
fuente
1
myip=$(curl -kLs "http://api.ipify.org")

o

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

Debería usar ip(en lugar de ifconfig) ya que es actual, se mantiene y, quizás lo más importante, para fines de secuencias de comandos, produce una salida coherente y analizable. Los siguientes son algunos enfoques similares:

Si desea la dirección IPv4 para su interfaz Ethernet eth0:

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

Como un guión:

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

La salida producida anteriormente está en notación CIDR. Si no se desea la notación CIDR, se puede quitar:

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

Otra opción que en mi humilde opinión es "más elegante" obtiene la dirección IPv4 para cualquier interfaz que se utilice para conectarse al host remoto especificado (8.8.8.8 en este caso). Cortesía de @gatoatigrado en esta respuesta :

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

Como un guión:

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

Esto funciona perfectamente bien en un host con una sola interfaz, pero más ventajosamente también funcionará en hosts con múltiples interfaces y / o especificaciones de ruta.

ipsería mi enfoque preferido, pero ciertamente no es la única forma de desollar a este gato. Aquí hay otro enfoque que utiliza hostnamesi prefiere algo más fácil / más conciso:

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

O, si desea la dirección IPv6:

$ hostname --all-ip-addresses | awk '{print $2}'  
Seamus
fuente
0

Necesitaba hacer esto dentro de un alias para iniciar un servidor de radio en mi NIC cableada. solía

ip addr | egrep -i "inet.+eth1" | awk -F[\ /] '{print $6}' | tr -d [:space:]
usuario208145
fuente
egrepes depreciado Usar en su grep -Elugar.
Yokai
0

Algunos comandos funcionan en centos 6 o 7, el siguiente comando funciona en ambos,

#!/bin/sh

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

echo $serverip
lakshmikandan
fuente
eso es demasiado grep | awk | awk. la línea se puede acortar a/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Archemar
Acepté, ¿puedes comprobar los centos6 y 7 ?. centos 7.x / sbin / ifconfig eth0 | awk '$ 1 == "inet" {print substr ($ 2,6); siguiente ; } '35.104.41 centos6.x (Funciona bien) / sbin / ifconfig eth0 | awk '$ 1 == "inet" {print substr ($ 2,6); siguiente ; } '192.168.0.1
lakshmikandan
0

Suponiendo que necesita su IP pública primaria como se ve desde el resto del mundo , pruebe cualquiera de los siguientes:

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

Este fragmento evita codificar el nombre del dispositivo (como 'eth0') y usará en iplugar de ifconfig:

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

Devolverá la IP del primer dispositivo activo listado en la salida de ip addr. Dependiendo de su máquina, esta puede ser una dirección ipv4 o ipv6.

Para almacenarlo en una variable, use:

ip=$(/sbin/ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/')
Philipp Claßen
fuente
0

todas las soluciones que usan awk / sed / grep parecen demasiado complejas y feas para mi situación ... así que se me ocurrió esta solución realmente simple PERO cuidado porque hace algunas suposiciones, a saber, la suposición de que la ÚLTIMA interfaz es la que estás interesado. si estás de acuerdo con eso, entonces esto está bastante limpio:

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

de lo contrario, podría hacer una ifdeclaración tonta para probar un prefijo específico o cualquier criterio que pueda tener.

mad.meesh
fuente
0

Comando simple para ajustar la dirección IP con la interfaz predeterminada.

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

Probado en todos los sistemas operativos Unix

MSArun
fuente
0

Puede que esta no sea la solución más sólida o correcta, pero a diferencia de la mayoría de las otras soluciones, el comando funciona tanto en Linux como en Mac (BSD).

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

Si está buscando una dirección IP pública del cuadro , puede usar lo siguiente:

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

Puede usar dig(1)opciones como -4o -6para buscar específicamente una dirección IPv4 o IPv6; Google proporcionará una respuesta en un registro de TXTtipo, que tendrá citas a su alrededor cuando sea presentado por dig; si desea usar posteriormente la variable con utilidades como traceroute, debe usar algo como tr (1) para eliminar dichas comillas.

Otras opciones incluyen whoami.akamai.nety myip.opendns.com, que responden con Ay AAAAregistros (en lugar de TXTcomo en el ejemplo anterior de Google), por lo que no requieren que se eliminen las comillas:

  • 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

Aquí hay un script de muestra que usa todas las opciones anteriores para establecer las variables:

#!/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}"

Si está buscando una dirección IP privada, o un conjunto de todas las direcciones IP asignadas a la caja, puede usar alguna combinación de ifconfig(en BSD y GNU / Linux), ip addr(en GNU / Linux), hostname(opciones -iy -Ien GNU / Linux) y netstatpara ver qué está pasando.

cnst
fuente
-2
hostname -I >> file_name 

esto hará todo lo que quieras

shanu
fuente
hostname: invalid option -- 'l'...
jasonwryan
Eso es una capital i. Parece funcionar bien, aunque aparentemente imprime las direcciones IP de todas las interfaces.
Joe
Se propone en una de las respuestas anteriores. Además, no almacena la IP en la variable. Entonces, ¿cuál es el punto de esta respuesta?
Jakuje