Utilitaire de ligne de commande Linux permettant de résoudre les noms d'hôtes en utilisant d'abord / etc / hosts


36

Il existe plusieurs utilitaires de ligne de commande pour les noms d'hôte de résolution ( host, dig, nslookup), mais ils utilisent tous des serveurs de noms exclusivement, tandis que les applications en aspect général en /etc/hostspremier ( en utilisant gethostbyname je crois).

Existe-t-il un utilitaire de ligne de commande permettant de résoudre les noms d’hôte qui se comporte comme une application habituelle, recherchant donc en /etc/hostspremier et ensuite uniquement en demandant à un serveur de noms?

(Je suis conscient que ce serait probablement comme 3 lignes de c, mais j'en ai besoin à l'intérieur d'un script shell quelque peu portable.)


Pourriez-vous s'il vous plaît expliquer votre situation un peu plus? Est-ce que ça awk '/hostname/ { print $1 }' /etc/hostsaide?
quanta

@quanta En réalité, la solution actuelle est la magie grep / sed sur / etc / hosts. Je voulais que cela soit plus général avec un repli.
Zulan

Réponses:


56

Ceci est facilement réalisé avec getent:

getent hosts 127.0.0.1

getentfera des recherches pour tout type de données configuré dans nsswitch.conf.


C’est l’outil que j’utilise dans mes conteneurs Alpine docker qui n’ont pas d’autre mécanisme comme digou nslookup.
Bruno Bronosky

26

Un outil qui pourrait fonctionner est getent. Donc, vous pouvez utiliser getent hosts www.google.com, ou getent hosts localhost. Il récupérera les entrées des bases de données comme spécifié dans la configuration de votre commutateur de service de noms /etc/nsswitch.conf.


1
Oui, mais cela ne retomberait pas sur le DNS.
slowpoison

Non, il le résout dans l'ordre nsswitch.conf.
cjc

@slowpoison, jetez un oeil à votre configuration nsswitch. Mon système a files dnspour les hôtes, ce qui signifie que / etc / hosts est consulté, puis le résolveur DNS. Votre configuration peut être différente.
Zoredache

@ cjc, c'est le cas. Je ne pense pas l'avoir essayé correctement.
slowpoison

@ Zoredache, je suis assez impressionné getent. Merci pour l'intro à cette commande.
slowpoison

8

Vous pouvez utiliser un wrapper gethostbyname () (obsolète) comme:

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

Ou un wrapper getaddrinfo () comme:

python -c 'import socket;print socket.getaddrinfo("www.google.com","http")[0][4][0]'

Notez que getaddrinfo retournera toutes les instances sous forme de liste. La dernière partie de la commande ne sélectionne que le premier tuple. Cela peut également renvoyer des adresses IPv6.


1
Cela fonctionnera, mais il est obsolète depuis un moment. Voir linux.die.net/man/3/gethostbyname .
Kyle Smith

Merci, je ne savais pas à ce sujet. ;)
Mircea Vutcovici

Avoir un vote positif. Aucun autre one-liner semi-portable n’a été proposé.
user239558

Au cas où cela serait utile à quelqu'un d'autre, j'ai créé une version Python 3 avec quelques options de ligne de commande: github.com/acdha/unix_tools/blob/master/bin/getaddrinfo
Chris Adams le

6

resolveip va le faire.

Bizarrement, cela fait partie des paquets mysql-server sur RHEL et Ubuntu.


6

Vous pouvez utiliser [votre langue préférée ici] pour écrire un script qui appelle getnameinfo . C'est comme ça que les binaires (comme ping) devraient le faire, donc vous êtes assuré de recevoir le même traitement.


6

Utilisez getent ahosts, par exemple:

$ getent ahosts www.google.com | sed -n 's/ *STREAM.*//p'
216.58.210.196
2a00:1450:4006:803::2004

Vous obtiendrez toutes les adresses IPv4 et IPv6 via le résolveur glibc (donc en utilisant d' /etc/hostsabord, comme cela est habituellement configuré dans /etc/nsswitch.conf).

Ne pas utiliser getent hosts, cela vous donnera des adresses IPv6 ou IPv4 (pas les deux), et le protocole choisi risque de ne pas être celui qui ne fonctionne pas. En effet, les adresses IPv6 sont généralement préférées, mais à certains endroits, les données IPv6 sont filtrées (non prises en charge) par les routeurs.


3

Version en ligne de commande "gethostbyname" :

#!/usr/bin/perl
use Socket;

$host = shift @ARGV;
die("usage: gethostbyname hostname\n") unless(defined($host));

$packed_ip = gethostbyname($host);

if (defined $packed_ip) {
    $ip_address = inet_ntoa($packed_ip);
    print "$ip_address\n";
    exit 0
} else {
    warn "$host not found\n";
    exit 1
}

2

Vous pourriez être vraiment hacky et utiliser arp:

arp -n somehostname | tr -d '()' | awk '{print $2}'

mais ce serait vraiment moche alors vous ne devriez pas faire ça.


2

getent hostsest cassé. Il préfère les adresses IPv6, gai.confdevrait être configuré pour préférer ipv4 mais ....

Le Perl gethostbynameutilise la priorité dans/etc/nsswitch.conf

hosts: files dns

Donc, cela fonctionne comme getent hostsdevrait fonctionner pour moi.

Également:

perl -e 'use Socket; print inet_ntoa(inet_aton("www.google.com")) . "\n";'

devrait marcher.


5
Ce n'est pas cassé, il n'utilise simplement pas getaddrinfo (qui lit /etc/gai.conf). Pour utiliser getaddrinfo, exécutez getent ahosts.
Craig65535

1

Essaye ça:

if [ `grep -c "hostname" /etc/hosts` -ge 1 ]; then
    ip=`awk '/hostname/ { print $1 }' /etc/hosts`
else
    ip=`host hostname | awk '/hostname has address/ { print $4 }'`
fi

-1

La commande suivante effectuera une recherche via DNS / etc / hosts sur une recherche directe du serveur DNS.

ping -W2 -c1 google.com | grep PING | sed -r "s/^[^\(]*\(([\.0-9]*)\).*/\1/"

Cette commande tente d'envoyer une requête ping à un domaine (dans ce cas, google.com) avec un délai d'attente de 2 secondes et d'obtenir la première ligne de la commande PING qui indique "PING google.com (216.58.199.36) 56 (84 ) octets de données ", puis utilisez Stream Editor (sed) pour détecter le premier ensemble de crochets et extraire les données qu’il contient, qui correspond à l’adresse IP recherchée.

Remarque: l'expression regex ne fonctionnera pas si l'URL contient des parenthèses (ou des crochets circulaires), mais ce serait un cas rare.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.