¿Cómo puedo obtener mi propia dirección IP y guardarla en una variable en un script de shell?
¿Cómo puedo obtener mi propia dirección IP y guardarla en una variable en un script de shell?
Respuestas:
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
grep
a 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)"
ifconfig eth0
ip address
en su lugar
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í.
ip
está disponible en todas las distribuciones de Red Hat y Fedora que he usado. ip
es parte del paquete iproute2 ( linuxfoundation.org/collaborate/workgroups/networking/iproute2 ). ifconfig
y route
supuestamente están en desuso, aunque muchas personas continúan usándolas, especialmente en los guiones. ip
es mucho más fácil de analizar, en mi opinión.
ip
tambié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.
ip
es 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
/sbin/ip
lugar de ip
?
awk
y cut
es 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] }'
¿Por qué no simplemente hacer IP=$(hostname -I)
?
hostname -i
me da solo 127.0.0.1
, hostname -I
me da la dirección IP correcta ...
-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
/etc/hosts
, junto con la dirección IP correspondiente
-I
en FreeBSD, pero puedes usarlodig +short `hostname -f`
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
ifdata
responde casi todas las preguntas por las que te sentirías tentado a analizar la ifconfig
salida.
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
ifdata
agregado iproute2
. Tal vez un nuevo binario llamadoipdata
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)
-o
utiliza 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 activosscope global
excluye direcciones privadas / locales como 127.0.0.1
yfe80::/64
primary
excluye direcciones temporales (suponiendo que desea una dirección que no cambie)-4
/ -6
filtrar 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 ' '
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.
ipa=$(ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$/\1/g')
ipa=$(hostname -i|cut -f2 -d ' ')
-I
lugar de -i
es mejor, ya que desearía ignorar las direcciones de bucle invertido, por lo que el comando final seríaipa=$(hostname -I|cut -f1 -d ' ')
grep
no es suficiente, no lo canalices a otra cosa. Sólo tiene que utilizar la otra cosa ( sed
, awk
, etc.).
No quiero ser un imbécil, pero realmente hay una manera correcta y esta es. Recorta la salida de ip route
para 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...
ip route get 8.8.8.8 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'
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
sed
comandoPrimero 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 ifconfig
a grep
a sed
a 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í sed
porque 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 src
campo.
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}}}'
Mis ifconfig
shows que tengo tun0
para mi VPN y eth0
para 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)
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.
En FreeBSD puedes usar
dig +short `hostname -f`
Esto puede funcionar para otros entornos, depende de su configuración.
/etc/resolv.conf
y 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.
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`
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 localhost
direcció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.
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.
ip
sería mi enfoque preferido, pero ciertamente no es la única forma de desollar a este gato. Aquí hay otro enfoque que utiliza hostname
si 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}'
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:]
egrep
es depreciado Usar en su grep -E
lugar.
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
grep | awk | awk
. la línea se puede acortar a/sbin/ifconfig eth0 | awk '$1 == "inet" { print substr($2,6); next ; } '
Este fragmento evita codificar el nombre del dispositivo (como 'eth0') y usará en ip
lugar 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'/')
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 if
declaración tonta para probar un prefijo específico o cualquier criterio que pueda tener.
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 -4
o -6
para buscar específicamente una dirección IPv4 o IPv6; Google proporcionará una respuesta en un registro de TXT
tipo, 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.net
y myip.opendns.com
, que responden con A
y AAAA
registros (en lugar de TXT
como 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 -i
y -I
en GNU / Linux) y netstat
para ver qué está pasando.
hostname -I >> file_name
esto hará todo lo que quieras
hostname: invalid option -- 'l'
...