¿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 .
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 }'
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.)
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 ...
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:
getent hosts unix.stackexchange.com | cut -d' ' -f1
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.
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")'
Simple pero útil:
getent ahostsv4 www.google.de | grep STREAM | head -n 1 | cut -d ' ' -f 1
getent ahostsv6 www.google.de | grep STREAM | head -n 1 | cut -d ' ' -f 1
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.
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)
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}'
Para completar la respuesta de Chris Down y abordar los comentarios de jfgagne sobre los alias (posiblemente encadenados), aquí hay una solución que:
/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
php -r "echo gethostbyname('unix.stackexchange.com');"
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}
)
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
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
}
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
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
.
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'
Dig +noall +answer +nocomments example.com | awk '{printf "%-36s\t%s\n", $1, $5 }'
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
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
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
#!/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! "
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.