Quelle est la manière la plus concise de résoudre un nom d'hôte en une adresse IP dans un script Bash? J'utilise Arch Linux .
Vous pouvez utiliser getent
, qui vient avec glibc
(donc vous l'avez presque certainement sur Linux). Cela se résout en utilisant gethostbyaddr/gethostbyname2, et vérifiera également /etc/hosts
/NIS/etc:
getent hosts unix.stackexchange.com | awk '{ print $1 }'
Ou, comme Heinzi l'a dit ci-dessous, vous pouvez utiliser Dig
avec le +short
argument (interroge directement les serveurs DNS, ne regarde pas /etc/hosts
/NSS/etc):
Dig +short unix.stackexchange.com
Si Dig +short
n'est pas disponible, l'un des éléments suivants devrait fonctionner. Toutes ces requêtes DNS directement et ignorent les autres moyens de résolution:
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 vous ne souhaitez imprimer qu'une seule adresse IP, ajoutez la commande exit
au flux de travail 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 }'
Avec Host
du paquet dnsutils :
$ Host unix.stackexchange.com
unix.stackexchange.com has address 64.34.119.12
( Nom du paquet corrigé selon les commentaires. À noter que d'autres distributions ont Host
dans différents paquets: Debian/Ubuntu bind9-Host, openSUSE bind-utils, Frugalware bind.)
J'ai un outil sur ma machine qui semble faire l'affaire. La page de manuel montre qu'il semble venir avec mysql ... Voici comment vous pouvez l'utiliser:
resolveip -s unix.stackexchange.com
64.34.119.12
La valeur de retour de cet outil est différente de 0 si le nom d'hôte ne peut pas être résolu:
resolveip -s unix.stackexchange.coma
resolveip: Unable to find hostid for 'unix.stackexchange.coma': Host not found
exit 2
UPDATE Sur Fedora, il est livré avec 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
Je suppose que cela créerait une étrange dépendance pour votre script ...
La commande suivante utilisant Dig
vous permet de lire le résultat directement sans sed/awk/etc. la magie:
$ Dig +short unix.stackexchange.com
64.34.119.12
Dig
est également inclus dans le package dnsutils
.
Remarque: Dig
a une valeur de retour de 0
, même si le nom n'a pas pu être résolu. Ainsi, vous devrez vérifier si la sortie est vide au lieu de vérifier la valeur de retour:
hostname=unix.stackexchange.com
ip=`Dig +short $hostname`
if [ -n "$ip" ]; then
echo IP: $ip
else
echo Could not resolve hostname.
fi
Remarque 2: si un nom d'hôte possède plusieurs adresses IP (essayez debian.org
, par exemple), tous seront retournés. Ce "problème" affecte jusqu'à présent tous les outils mentionnés dans cette question:
getent hosts unix.stackexchange.com | cut -d' ' -f1
Les solutions proposées jusqu'à présent fonctionnent principalement dans le cas le plus simple: le nom d'hôte se résout directement en une seule adresse IPv4. Cela peut être le seul cas où vous devez résoudre les noms d'hôte, mais sinon, vous trouverez ci-dessous une discussion sur certains cas que vous devrez peut-être gérer.
Chris Down et Heinzi ont brièvement discuté du cas où le nom d'hôte se résout en plusieurs adresses IP. Dans ce cas (et dans d'autres ci-dessous), les scripts de base sous l'hypothèse qu'un nom d'hôte se résout directement en une seule adresse IP peuvent se casser. Ci-dessous, un exemple avec un nom d'hôte se résolvant à plusieurs adresses 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
Mais comment ça www.l.google.com
? C'est là que le cas d'alias doit être introduit. Vérifions l'exemple ci-dessous:
$ 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
Donc www.google.com
ne se résout pas directement aux adresses IP, mais à un alias qui se résout lui-même à plusieurs adresses IP. Pour plus d'informations sur les alias, consultez ici . Bien sûr, le cas où un alias a une seule adresse IP est possible, comme indiqué ci-dessous:
$ 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
Mais les alias peuvent-ils être enchaînés? La réponse est oui:
$ 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
Je n'ai trouvé aucun exemple où un nom d'hôte se résout en un alias qui ne se résout pas en une adresse IP, mais je pense que le cas peut se produire.
Plus que plusieurs adresses IP et alias, existe-t-il d'autres cas particuliers ... qu'en est-il d'IPv6? Tu pourrais essayer:
$ 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
Où le nom d'hôte ipv6.google.com
est un nom d'hôte uniquement IPv6. Qu'en est-il des noms d'hôte à double pile:
$ 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::
Encore une fois à propos d'IPv6, si votre hôte est uniquement IPv4, vous pouvez toujours résoudre les adresses IPv6 (testé sur IPv4 uniquement WinXP et avec ipv6.google.com, vous pouvez l'essayer sous Linux). Dans ce cas, la résolution réussit, mais un ping échoue avec un message d'erreur hôte inconnu. Il peut s'agir d'un cas où votre script échoue.
J'espère que ces remarques ont été utiles.
Pour éviter le problème avec les alias et toujours obtenir une seule adresse IP prête à l'emploi:
python -c 'import socket; print socket.gethostbyname("www.example.com")'
Simple mais utile:
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
Toutes les commandes résoudront une adresse IP si l'hôte existe toujours. Si l'hôte pointe vers CNAME, il obtiendra également l'IP dans ce cas.
La première commande renvoie l'adresse IPv4 résolue
La deuxième commande renvoie l'adresse IPv6 résolue
La troisième commande renverra l'adresse préférée des propriétaires, à savoir l'adresse IPv4 ou IPv6.
ping -q -c 1 -t 1 your_Host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"
fonctionne sans dépendances sur d'autres systèmes (et pour les hôtes spécifiés dans/etc/hosts)
Voici une légère variation de l'approche ping
qui prend en compte "Host inconnu" (en passant par stderr) et utilise tr
pour éviter l'utilisation de sed
regexps:
ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d '():' | awk '/^PING/{print $3}'
Dans le cas où il est important de capturer la valeur de sortie, les éléments suivants fonctionneront (bien que moins élégants):
ping -c1 -t1 -W0 www.example.com &>/dev/null && ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d '():' | awk '/^PING/{print $3}'
Pour compléter la réponse de Chris Down et répondre aux commentaires de jfgagne sur les alias (éventuellement chaînés), voici une solution qui:
/etc/hosts
fichier (dans mon cas, je ne le voulais pas); pour l'interroger, la solution python de dbernt est parfaite)n'utilise pas awk/sed
Dig +short www.alias.com | grep -v "\.$" | head -n 1
Renvoie toujours la première adresse IP, ou vide si elle n'est pas résolue. avec la version de Dig:
$ Dig -v
Dig 9.8.1-P1
php -r "echo gethostbyname('unix.stackexchange.com');"
J'aurais aimé ajouter ceci comme commentaire à Andrew McGregor Re: ping. Cependant, cela ne me permettrait pas, donc je dois ajouter ceci comme une autre réponse. (Si quelqu'un peut le déplacer dans un commentaire, n'hésitez pas à le faire.)
Ceci est une autre variante, utilisant uniquement ping et grep:
ping -q -c1 -t1 your_Host_here | grep -Eo "([0-9]+\.?){4}"
grep -E
pour l'expression régulière étendue et grep -o
pour renvoyer uniquement la partie correspondante. l'expression rationnelle elle-même recherche un ou plusieurs chiffres ([0-9]+
) et éventuellement un point (\.?
) quatre fois ({4}
)
nmap -sP 192.168.178.0/24|grep YOUR_HOSTNAME|sed -n 's/.*[(]\([0-9\.]*\)[)].*/\1/p'
était la solution que j'ai trouvée sans serveur DNS
voici une recette Bash que j'ai concoctée en utilisant les réponses d'autres personnes - premiers essais /etc/hosts
, puis revient à 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
}
Vous pouvez utiliser 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
Peut-être pas le plus concis, mais il semble être robuste et efficace:
# $(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
}
Cela produira une seule IP IPv4 et renverra 1
en cas de panne, tout en masquant la sortie stderr.
Vous pouvez l'utiliser comme ceci:
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
L'IP de Google est 216.58.192.46.
Si vous souhaitez plutôt une adresse IPv6, remplacez simplement -4
avec -6
.
Dig est trop lent, nslookup est beaucoup plus rapide
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 ligne résout une liste de nom d'hôte
for LINE in `cat ~/Desktop/mylist`; do a=$(nslookup $LINE | awk '/^Address: / { print $1 }'); echo $a >> ~/Desktop/ip; done
Je ne connais pas le moyen le plus simple pour un script bash mais si vous voulez résoudre un nom d'hôte et voir si l'hôte est en place, utilisez ping
!
ping -a hostname -c 1
ping
l'hôte une fois et résoudra le nom d'hôte en adresse 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
Je le fais tout le temps sur mon Mac qui n'a pas getent
. ping
ressemble à un hack. Je voudrais prendre /etc/hosts
également.
J'ai donc écrit un emballage stupide pour dns.lookup
pour vous qui avez installé Node.js pour fournir une 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! "
Oui, il existe déjà de nombreuses réponses, mais il manque une solution utilisant Perl:
Perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com
Dans un script bash, il pourrait être utilisé comme ceci:
#!/bin/bash
ipaddr=$(Perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com)
echo $ipaddr
Les modules utilisés ici sont des modules de base, donc devraient être disponibles partout sans installation avec CPAN.