¿Cómo puedo convertir un nombre de host en una dirección IP en un script Bash?

¿Cuál es la forma más concisa de resolver un nombre de host en una dirección IP en un script Bash? Estoy usando Arch Linux .

Comentarios

  • Es una pena que la getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname> responda está en algún lugar cerca del fondo. Es ‘ el más simple, no requiere paquetes adicionales y es más fácil analizar desde un script Bash también.
  • @ 0xC0000022L: La nueva vergüenza es que esa respuesta sugiere getent hosts somehost, cuando ejecuta esto mientras está en somehost producirá una dirección IPv6 , que es diferente de la mayoría de las otras herramientas (ping, ssh al menos) resuelve nombres y rompe algunas cosas. Utilice ahosts en lugar de hosts.
  • @j_random_hacker: que le impide solicitar específicamente IPv4 (ahostsv4) o direcciones IPv6 (ahostsv6)? Personalmente, no encuentro nada malo en que la solicitud no específica devuelva IPv6. Su código debe estar preparado. IPv6 existe desde hace más de 20 años.
  • @ 0xC0000022L: nadie » me impide » haciendo eso, pero la respuesta sugiere específicamente hosts, y hasta ahora 4 personas han votado a favor de vinc17 ‘ que expresa el dolor causado por » repentinamente IPv6 «. Estar preparado para IPv6 no siempre es el problema: muchos programas necesitan una forma de determinar si dos nombres / direcciones se refieren al mismo host. Pueden usar una simple coincidencia de cadenas o deben saber mucho sobre la red para encontrar la respuesta » true «. Este último es un campo minado, tantos programas y sistemas de terceros, sobre los que no tengo control, usan el primero.

Respuesta

Puede usar getent, que viene con glibc (por lo que es casi seguro que lo tenga en Linux) . Esto se resuelve usando gethostbyaddr / gethostbyname2, por lo que también verificará /etc/hosts / NIS / etc:

getent hosts unix.stackexchange.com | awk "{ print $1 }" 

O bien, como Heinzi dijo a continuación, puede usar dig con el argumento +short (consulta los servidores DNS directamente, no mira /etc/hosts / NSS / etc):

dig +short unix.stackexchange.com 

Si dig +short no está disponible, cualquiera de lo siguiente debería funcionar. Todos estos consultan DNS directamente e ignoran otros medios de resolución:

host unix.stackexchange.com | awk "/has address/ { print $4 }" nslookup unix.stackexchange.com | awk "/^Address: / { print $2 }" dig unix.stackexchange.com | awk "/^;; ANSWER SECTION:$/ { getline ; print $5 }" 

Si solo desea imprimir una IP, agregue la exit comando al flujo de trabajo de awk«.

dig +short unix.stackexchange.com | awk "{ print ; exit }" getent hosts unix.stackexchange.com | awk "{ print $1 ; exit }" host unix.stackexchange.com | awk "/has address/ { print $4 ; exit }" nslookup unix.stackexchange.com | awk "/^Address: / { print $2 ; exit }" dig unix.stackexchange.com | awk "/^;; ANSWER SECTION:$/ { getline ; print $5 ; exit }" 

Comentarios

  • De forma predeterminada, el uso de dig solo funciona con ipv4, donde el host proporciona respuestas tanto ipv4 como ipv6. Esto puede ser inesperado. Puede probar host www.google.com, dig +short www.google.com, host ipv6.google.com, dig +short ipv6.google.com, host www.facebook.com , dig +short www.facebook.com.
  • DIG no funciona, si es un CNAME no devolverá la IP.
  • A veces, host se puede agotar el tiempo de espera y no devuelve nada. Para algunos dominios, dig +short puede devolver un alias de dominio en la primera línea. Por lo tanto, para asegurarse de que la salida sea IPv4 dirección, utilice dig +short example.com | grep -Eo '[0-9\.]{7,15}' | head -1.
  • El uso de getent hosts <host> es incorrecto, como para instan ce puede dar una dirección IPv6 mientras que IPv6 no ‘ no funciona. La solución correcta es usar getent ahosts <host> para probar tanto IPv6 como IPv4 si es necesario.
  • Vale la pena mencionar: host, dig y nslookup parecen hablar directamente con los servidores enumerados en resolv.conf, mientras que » getent hosts » respetan tanto el archivo de hosts locales como el almacenamiento en caché a nivel de biblioteca (como nscd) si está habilitado .

Responda

Con host del paquete dnsutils :

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

( Corregido nombre del paquete de acuerdo con los comentarios. Como nota, otras distribuciones tienen host en paquetes diferentes: Debian / Ubuntu bind9-host , openSUSE bind-utils , Frugalware bind .)

Comentarios

  • Consulte la entrada de resolveip a continuación si necesita resolver algo que no está en DNS (por ejemplo, / etc / hosts)
  • Tenga en cuenta que host a veces devuelve una salida de varias líneas (en el caso de las redirecciones), ‘ querrás host unix.stackexchange.com | tail -n1 si solo desea la línea con la dirección IP.
  • Hay varias versiones de » host » con diferentes formatos de salida. P.ej. la mayoría de los sistemas parecen tener la versión BIND9, pero mi servidor Ubuntu 10.04 LTS tiene una versión completamente diferente de alguna manera ..
  • si no ‘ no tiene host o dig instalado, puede usar ping en su lugar, que siempre está disponible: ping unix.stackexchange.com -c 1 -q 2>&1 | grep -Po "(\d{1,3}\.){3}\d{1,3}" esto no necesita Los paquetes adicionales se instalan en la mayoría de las combinaciones de Unix / Linux.
  • Esta respuesta merece una seria negativa. host es una herramienta de DNS (similar a nslookup) por lo que solo busca hosts en DNS, no en p. ej. /etc/hosts. Por lo tanto, NO es una respuesta a la pregunta de OP ‘.

Respuesta

Tengo una herramienta en mi máquina que parece hacer el trabajo. La página de manual muestra que parece venir con mysql … Así es como se puede usar:

resolveip -s unix.stackexchange.com 64.34.119.12 

El valor de retorno de esta herramienta es diferente de 0 si el nombre de host no se puede resolver:

resolveip -s unix.stackexchange.coma resolveip: Unable to find hostid for "unix.stackexchange.coma": host not found exit 2 

ACTUALIZAR En fedora, viene con mysql-server:

yum provides "*/resolveip" mysql-server-5.5.10-2.fc15.x86_64 : The MySQL server and related files Dépôt : fedora Correspondance depuis : Nom de fichier : /usr/bin/resolveip 

Supongo que crearía una dependencia extraña para su script …

Comentarios

  • Esta parece ser la única solución aquí que usa el sistema operativo ‘ s compilado en resolver, por lo que funciona para / etc / hosts así como DNS.
  • getent, como se detalla en la otra respuesta, también mira / etc / hosts y viene con glibc, por lo que no tiene dependencias en un sistema Linux.
  • No usaría resolveip ya que crea una dependencia en otro paquete. getent está instalado de forma predeterminada. host, nslookup y dig están todos en paquetes opcionales. Definitivamente use getent en un script.
  • Me gusta esta respuesta pero no ‘ t devuelve ipv6

Responder

El siguiente comando que usa dig le permite leer el resultado directamente sin sed / awk / etc. magia:

$ dig +short unix.stackexchange.com 64.34.119.12 

dig también se incluye en el dnsutils paquete.


Nota : dig tiene un valor de retorno de 0, incluso si el nombre no se pudo resolver. Por lo tanto, «debe verificar si la salida está vacía en lugar de verificar el valor de retorno:

hostname=unix.stackexchange.com ip=`dig +short $hostname` if [ -n "$ip" ]; then echo IP: $ip else echo Could not resolve hostname. fi 

Nota 2 : Si un nombre de host tiene varias direcciones IP (prueba debian.org, por ejemplo), todas serán Este «problema» afecta a todas las herramientas mencionadas en esta pregunta hasta ahora:

Comentarios

  • Tenga en cuenta que si un dominio tiene una entrada CNAME su dominio puede estar impreso en la primera línea en lugar de una dirección IP.

Respuesta

getent hosts unix.stackexchange.com | cut -d" " -f1 

Comentarios

  • También considere ahosts, ahostsv4, ahostsv6 con getent.
  • cut no getent ‘ s, que utilizan \t para separar columnas. Este es el caso de Solaris.
  • @ceving: En Sola ris, puede que tenga que ejecutar cut sin -d (el valor predeterminado es \t como delimitador). En Linux, ‘ s espacios, por lo que la línea anterior funciona.

Respuesta

Las soluciones dadas hasta ahora funcionan principalmente en el caso más simple: el nombre de host se resuelve directamente en una única dirección IPv4. Este podría ser el único caso en el que necesita resolver nombres de host, pero si no es así, a continuación se muestra una discusión sobre algunos casos que podría necesitar manejar.

Chris Down y Heinzi discutieron brevemente el caso donde se resuelve el nombre de host a más de una dirección IP. En este caso (y en otros a continuación), las secuencias de comandos básicas bajo el supuesto de que un nombre de host se resuelve directamente en una única dirección IP puede fallar. A continuación, un ejemplo con un nombre de host que se resuelve en más de una única dirección IP:

$ host www.l.google.com www.l.google.com has address 209.85.148.147 www.l.google.com has address 209.85.148.103 www.l.google.com has address 209.85.148.99 www.l.google.com has address 209.85.148.106 www.l.google.com has address 209.85.148.105 www.l.google.com has address 209.85.148.104 

Pero, ¿qué es www.l.google.com ? Aquí es donde se debe introducir el caso alias . Veamos el siguiente ejemplo:

$ host www.google.com www.google.com is an alias for www.l.google.com. www.l.google.com has address 74.125.39.103 www.l.google.com has address 74.125.39.147 www.l.google.com has address 74.125.39.105 www.l.google.com has address 74.125.39.99 www.l.google.com has address 74.125.39.106 www.l.google.com has address 74.125.39.104 

Entonces www.google.com no se resuelve directamente en direcciones IP, sino en un alias que a su vez se resuelve en varias direcciones IP. Para obtener más información sobre los alias, consulta aquí . Por supuesto, el caso en el que un alias tiene una sola dirección IP es posible , como se muestra a continuación:

$ host g.www.ms.akadns.net g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net. lb1.www.ms.akadns.net has address 207.46.19.190 

Pero, ¿se pueden encadenar los alias?La respuesta es sí:

$ host www.microsoft.com www.microsoft.com is an alias for toggle.www.ms.akadns.net. toggle.www.ms.akadns.net is an alias for g.www.ms.akadns.net. g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net. lb1.www.ms.akadns.net has address 207.46.19.254 $ host www.google.fr www.google.fr is an alias for www.google.com. www.google.com is an alias for www.l.google.com. www.l.google.com has address 74.125.39.147 www.l.google.com has address 74.125.39.103 www.l.google.com has address 74.125.39.99 www.l.google.com has address 74.125.39.106 www.l.google.com has address 74.125.39.104 www.l.google.com has address 74.125.39.105 

No encontré ningún ejemplo en el que un nombre de host se resuelva en un alias que no se resuelva en una dirección IP, pero creo que Este caso podría ocurrir.

Más que múltiples direcciones IP y alias, hay otros casos especiales … ¿qué pasa con IPv6? Puede intentar:

$ host ipv6.google.com ipv6.google.com is an alias for ipv6.l.google.com. ipv6.l.google.com has IPv6 address 2a00:1450:8007::68 

Donde el nombre de host ipv6.google.com es un nombre de host de sólo IPv6. ¿Qué pasa con los nombres de host de doble pila:

$ host www.facebook.com www.facebook.com has address 66.220.153.15 www.facebook.com has IPv6 address 2620:0:1c08:4000:face:b00c:: 

Nuevamente sobre IPv6, si su host es solo IPv4, aún puede resolver direcciones IPv6 (probado en IPv4 solo WinXP y con ipv6.google.com, podría probarlo en Linux). En este caso, la resolución tiene éxito, pero un ping falla con un mensaje de error de host desconocido . Este podría ser un caso en el que su secuencia de comandos falla.

Espero que esos comentarios hayan sido útiles.

Comentarios

  • Qué gran complementar a la respuesta aceptada, mostrando todos los casos extremos con los que uno podría querer lidiar en el guión. Mi versión host ni siquiera indica que » tiene la dirección » para mis cajas.

Respuesta

Para evitar el problema con los alias y tener siempre una única dirección IP lista para usar:

python -c "import socket; print socket.gethostbyname("www.example.com")" 

Comentarios

Respuesta

ping -q -c 1 -t 1 your_host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//" 

funciona sin dependencias de otros sistemas (y para los hosts especificados en / etc / hosts)

Comentarios

  • El uso de ping es lo que necesitaba, ya que necesito el valor del archivo de hosts pero el patrón sed se analiza correctamente pero esto funcionó ping – q -c 1 -t 1 your_host_here | grep PING | sed -e » s / ^ [^ (] * [(] // » | sed -e » s / [)]. * $ // »
  • Para resolver algo en mi red doméstica como myhostname.local, esto funciona para yo esta es la mejor respuesta.
  • Puedo sugerir esto también: ping -q -c 1 -t 1 bahface.local | grep -m 1 PING | cut -d "(" -f2 | cut -d ")" -f1
  • getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname> también funciona para declaraciones dentro de /etc/hosts … y ‘ es la herramienta de acceso para todo tipo de bases de datos del sistema (passwd, grupo, alias, servicios).

Respuesta

Simple pero útil :

  1. getent ahostsv4 www.google.de | grep STREAM | head -n 1 | cut -d " " -f 1
  2. getent ahostsv6 www.google.de | grep STREAM | head -n 1 | cut -d " " -f 1
  3. getent hosts google.de | head -n 1 | cut -d " " -f 1

Todos los comandos resolverán una dirección IP si el host aún existe. Si el host apunta a un CNAME, también obtendrá la IP en ese caso.

El primer comando devuelve la dirección IPv4 resuelta.

El segundo comando devuelve la res dirección IPv6 guardada.

El tercer comando devolverá la dirección preferida del propietario, que puede ser una dirección IPv4 o IPv6.

Comentarios

  • De lejos, el más simple. Y está disponible por defecto. No como host que requieren la instalación de la bindutils

Respuesta

Aquí hay una ligera variación del enfoque ping que tiene en cuenta el «host desconocido» (mediante canalización a través de stderr) y utiliza tr para evitar el uso de sed regexps:

ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d "():" | awk "/^PING/{print $3}" 

En caso es importante capturar el valor de salida, entonces lo siguiente funcionará (aunque menos elegante):

ping -c1 -t1 -W0 www.example.com &>/dev/null && ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d "():" | awk "/^PING/{print $3}" 

Comentarios

  • Me encanta esta solución, porque funciona sin herramientas adicionales.

Responder

Para completar la respuesta de Chris Down y abordar los comentarios de jfgagne sobre alias (posiblemente encadenados), aquí hay una solución que:

  • toma en cuenta múltiples IP
  • uno o más alias (CNAME)
  • no consulta el archivo /etc/hosts ( en mi caso no lo quería); para consultarlo, la solución de Python de dbernt es perfecta)
  • no usa awk / sed

    dig +short www.alias.com | grep -v "\.$" | head -n 1 

Siempre devuelve la primera dirección IP, o tring vacío si no se resuelve. con la versión de dig:

 $ dig -v DiG 9.8.1-P1 

Comentarios

  • Gracias, otras respuestas asumen que » dig + short » siempre devuelve una sola dirección IP. No eran ‘ t contabilizando CNAME.

Respuesta

 php -r "echo gethostbyname("unix.stackexchange.com");" 

Comentarios

  • esto funciona, pero requiere que php esté instalado en su terminal
  • puede ser útil en un contenedor docker típico de php donde » host «, » dig » etc. no están disponibles

Respuesta

Me hubiera gustado agregar esto como comentario a Andrew McGregor Re: ping. Sin embargo, no me lo permitió, así que necesito agregar esto como otra respuesta. (Si alguien puede moverlo a un comentario, no dude en hacerlo).

Esta es otra variante, solo usando ping y grep :

ping -q -c1 -t1 your_host_here | grep -Eo "([0-9]+\.?){4}" 

grep -E para expresiones regulares extendidas y grep -o para devuelve solo la parte correspondiente. La expresión regular busca uno o varios dígitos ([0-9]+) y, opcionalmente, un punto (\.?) cuatro veces ( {4})

Respuesta

Podría usar host:

hostname=example.org # strips the IP IP=$( host ${hostname} | sed -e "s/.*\ //" ) # checks for errors if [ $? -ne 0 ] ; then echo "Error: cannot resolve ${hostname}" 1>&2 exit 1; fi 

Responde

aquí «una receta de Bash Cociné usando las respuestas de otras personas: primero prueba /etc/hosts, luego recurre a nslookup:

 resolveip(){ local host="$1" if [ -z "$host" ] then return 1 else local ip=$( getent hosts "$host" | awk "{print $1}" ) if [ -z "$ip" ] then ip=$( dig +short "$host" ) if [ -z "$ip" ] then echo "unable to resolve "$host"" >&2 return 1 else echo "$ip" return 0 fi else echo "$ip" return 0 fi fi }  

Comentarios

  • Para ser claros, getent hosts isn ‘ es solo una búsqueda en / etc / hosts; es ‘ una llamada completa de resolución de DNS a gethostbyaddr (3) , y ‘ es muy poco probable que falle en un caso en el que dig tendrá éxito. Consulte la página de manual de getent .
  • @Stuart tiene razón: ‘ he aprendido mucho desde que escribí eso y simplificó demasiado un comando poderoso. getent sigue siendo mi favorito, aunque también me gusta dig +short

Responder

nmap -sP 192.168.178.0/24|grep YOUR_HOSTNAME|sed -n "s/.*[(]\([0-9\.]*\)[)].*/\1/p" 

fue la solución que encontré sin servidor DNS

Respuesta

Quizás no sea el más conciso, pero parece robusto y eficiente:

# $(get_host_dns_short "google.com") # # Outputs the IPv4 IP Address of a hostname, resolved by DNS. Returns 0 if DNS # responded successfully; 1 otherwise. Will mask error output. function get_host_dns_short() { ( set -o pipefail host -4 -W1 -t A "$1" 2>/dev/null | awk "/has address/ { print $NF; exit }" ) && return 0 || return 1 } 

Esto generará un único IPv4 IP, así como devolver 1 en caso de falla, mientras enmascara la salida stderr.

Puede usarlo así:

GOOGLE_IP="$(get_host_dns_short "google.com")" if [[ $? -eq 0 ]]; then echo "Google"s IP is ${GOOGLE_IP}." else echo "Failed to resolve Google"s IP." fi 

La IP de Google es 216.58.192.46.

Si desea una dirección IPv6 en su lugar, simplemente reemplace -4 con -6.

Respuesta

dig +noall +answer +nocomments example.com | awk "{printf "%-36s\t%s\n", $1, $5 }"

Comentarios

  • Algún contexto de cómo esa respuesta mejora sobre las ya existentes Se bueno. Además, sangra los comandos con 4 espacios (cf. la sintaxis de rebajas).

Respuesta

dig es demasiado lento, nslookup es mucho más rápido

nslookup google.com | grep -Po "Address:\s*[0-9.]+" | tail -1 | sed -e "s/Address:\s*//g" 

Responder

1 línea resuelve una lista del nombre de host

for LINE in `cat ~/Desktop/mylist`; do a=$(nslookup $LINE | awk "/^Address: / { print $1 }"); echo $a >> ~/Desktop/ip; done 

Responder

Estoy haciendo esto todo el tiempo en mi Mac que no tiene getent. ping parece un truco. También me gustaría tener en cuenta /etc/hosts.

Entonces, escribí una envoltura estúpida para dns.lookup para usted que tiene Node.js instalado para proporcionar una CLI:

$ npm install -g lookup-hostname $ lookup google.com 62.243.192.89 

Comentarios

  • 60% de probabilidad de rotura antes de que te acerques a una resolución.
  • @dotbit, ¿podrías dar más detalles? ‘ he usado esto semanalmente desde ‘ 17 y nunca he tenido problemas.
  • @Jensen pero tú ‘ eres el único en la historia, como siempre. El resto de nosotros usualmente nos encontramos con FAIL de un tipo u otro, y siempre.
  • » como siempre » ¿Qué quieres decir con eso? » El resto de nosotros » ¿Quién ‘ es ese ? » se encuentra con FAIL » ¿Qué problema específico está viendo? ‘ tengo curiosidad.

Responder

No » No conozco la forma más fácil de ejecutar un script bash, pero si desea resolver un nombre de host y ver si el host está activo, use ping!

ping -a hostname -c 1 

Se ping el host una vez y se resuelve el nombre del host en la dirección IP.

$ ping -a www.google.com -c 1 PING www.google.com (216.58.211.132) 56(84) bytes of data. 64 bytes from arn09s10-in-f4.1e100.net (216.58.211.132): icmp_seq=1 ttl=54 time=1.51 ms 

Comentarios

  • usar ping es bueno, porque todo el mundo lo tiene, pero es necesario filtrar la parte IP de las salidas, si desea usarla en un script.

Responder

Sí, ya hay muchas respuestas, pero falta una solución que use perl:

perl -MSocket -MNet::hostent -E "say inet_ntoa((gethost shift)->addr)" unix.stackexchange.com 

En un script bash se podría usar así:

#!/bin/bash ipaddr=$(perl -MSocket -MNet::hostent -E "say inet_ntoa((gethost shift)->addr)" unix.stackexchange.com) echo $ipaddr 

Los módulos que se utilizan aquí son módulos principales, por lo que deberían estar disponibles en todas partes sin necesidad de instalarlos con CPAN.

Comentarios

  • perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com 2>/dev/null es mucho más limpio. pero nadie más que nosotros dos estamos usando p ö rl, todos los demás usan Pascal Script, por supuesto.
  • En realidad, prefiero ver los mensajes de error en todo caso va mal. Can't call method "addr" on an undefined value no es ‘ t exactamente el mejor mensaje de error, pero puede dar una pista sobre el problema.

Respuesta

#!/bin/bash systemd-resolve RT.com -t A | awk "{ print $4 ; exit }" systemd-resolve unix.stackexchange.com -t A --legend=no | awk "{ print $4 ; exit }" resolveip -s RT.com dig +short RT.com host RT.com | awk "/has address/ { print $4 }" nslookup RT.com | awk "/^Address: / { print $2 }" ping -q -c 1 -t 1 RT.com | grep PING | sed -e "s/).*//" | sed -e "s/.*(//" ruby -rresolv -e " print Resolv.getaddress "RT.com" " python2 -c "import socket; print socket.gethostbyname("RT.com")" perl -MSocket -MNet::hostent -E "say inet_ntoa((gethost shift)->addr)" RT.com 2>/dev/null php -r "echo gethostbyname( "RT.com" );" echo " all do work for me - take your pick! " 

Comentarios

  • La versión ruby imprime comillas alrededor de la dirección IP — probablemente se debería usar print en lugar de p.
  • gracias, @Slaven Rezic y siéntete libre de votar. de nuevo, aquí en la parte inferior, el script puede ser más visible en realidad … 😉

Responder

host -t a cisco.com 

este comando mostrará la dirección IP (cambiará el dominio a IP)

Respuesta

Además de la solución anterior, puede traducir varios nombres de host a ip a través del siguiente script, la única dependencia es el comando «ping» en el núcleo de Unix:

getip(){ ping -c 1 -t 1 $1 | head -1 | cut -d " " -f 3 | tr -d "()" 2>&1 | tee >> /tmp/result.log & } getip "hostname.number1.net" getip "hostname.number2.net" getip "hostname.number3.net" getip "hostname.number4.net" getip "hostname.number5.net" getip "hostname.number6.net" getip "hostname.number7.net" getip "hostname.number8.net" 
$ cat /tmp/result.log ABC.DEF.GHI.XY1 ABC.DEF.GHI.XY2 ABC.DEF.GHI.XY3 ABC.DEF.GHI.XY4 ABC.DEF.GHI.XY5 ABC.DEF.GHI.XY6 ABC.DEF.GHI.XY7 ABC.DEF.GHI.XY8 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *