it-swarm-es.tech

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

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

450
Eugene Yarmash

Puede usar getent, que viene con glibc (por lo que casi seguro lo tiene 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, como dijo Heinzi a continuación, puede usar Dig con el +short argumento (consulta los servidores DNS directamente, no mira /etc/hosts/NSS/etc):

Dig +short unix.stackexchange.com

Si Dig +short no está disponible, cualquiera de los siguientes 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 el comando exit 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 }'
570
Chris Down

Con Host del paquete dnsutils :

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

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

146
manatwork

Tengo una herramienta en mi máquina que parece hacer el trabajo. La página del manual muestra que parece venir con mysql ... Así es como podría usarlo:

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

UPDATE 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 tu script ...

56
greg0ire

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 paquete dnsutils.


Nota: Dig tiene un valor de retorno de 0, incluso si el nombre no se pudo resolver. Por lo tanto, deberá 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 múltiples direcciones IP (intente debian.org, por ejemplo), todos serán devueltos. Este "problema" afecta a todas las herramientas mencionadas en esta pregunta hasta ahora:

45
Heinzi
getent hosts unix.stackexchange.com | cut -d' ' -f1
44
sborsky

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

Chris Down y Heinzi discutieron brevemente el caso en el que el nombre de host se resuelve en más de una dirección IP. En este caso (y otros a continuación), la secuencia de comandos básica bajo el supuesto de que un nombre de host se resuelve directamente en una sola dirección IP puede romperse. A continuación, un ejemplo con un nombre de host que se resuelve en más de una sola 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 que es www.l.google.com? Aquí es donde debe introducirse 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 se resuelve en varias direcciones IP. Para obtener más información sobre alias, marque 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 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 el caso podría ocurrir.

Más que múltiples direcciones IP y alias, ¿hay otros casos especiales ... ¿qué pasa con IPv6? Tu podrías 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 solo 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 un WinXP solo IPv4 y con ipv6.google.com, puede probarlo en Linux). En este caso, la resolución tiene éxito, pero un ping falla con un ¡mensaje de error del Host desconocido. Este podría ser un caso en el que su script falla.

Espero que esas observaciones hayan sido útiles.

30
jfg956

Para evitar el problema con los alias y obtener siempre una sola dirección IP lista para usar:

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

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 aún existe Host. Si Host apunta a CNAME, también obtendrá la IP en ese caso.

El primer comando devuelve la dirección IPv4 resuelta

El segundo comando devuelve la dirección IPv6 resuelta

El tercer comando devolverá la dirección preferida de los propietarios, que puede ser la dirección IPv4 o IPv6.

19
Tom Freudenberg
ping -q -c 1 -t 1 your_Host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"

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

19
Andrew McGregor

Aquí hay una ligera variación del enfoque ping que toma en cuenta "Host desconocido" (canalizando a través de stderr) y usa 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 de que sea importante capturar el valor de salida, 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}'
9
Stefan Farestam

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

  • toma en cuenta múltiples IP
  • tiene en cuenta uno o más alias (CNAME)
  • no consulta /etc/hosts archivo (en mi caso no lo quería); para consultarlo, dbernt python 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 versión de Dig:

    $ Dig -v
    Dig 9.8.1-P1
8
Franck
 php -r "echo gethostbyname('unix.stackexchange.com');"
6
Mohammed Zourob

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, siéntase libre de 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 devolver solo la parte coincidente. la expresión regular en sí busca uno o varios dígitos ([0-9]+) y opcionalmente un punto (\.?) cuatro veces ({4})

6
Dweia
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

5
Philippe Gachoud

aquí hay una receta de Bash que preparé usando las respuestas de otras personas - primero intenta /etc/hosts, luego vuelve 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
}
5
RubyTuesdayDONO

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
5
Matteo

Quizás no sea el más conciso, pero parece ser 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á una sola IP IPv4, y devolverá 1 en caso de falla, mientras se enmascara la salida stderr.

Puedes 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, simplemente reemplace -4 con -6.

4
Will

La excavación es demasiado lenta, nslookup es mucho más rápido

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

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

4
D P Baker

1 línea resuelve una lista de nombre de host

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

No conozco la forma más fácil para 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

Will ping el Host una vez y resolverá el nombre del host a 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
3
user257655

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

Entonces, escribí un estúpido envoltorio 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
3
Thomas Jensen
#!/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!  "
2
dotbit

Sí, ya hay muchas respuestas, pero falta una solución con 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 utilizados aquí son módulos centrales, por lo que deberían estar disponibles en todas partes sin instalar con CPAN.

2
Slaven Rezic