Linux-Befehlszeilenprogramm zum Auflösen von Hostnamen mithilfe von / etc / hosts

36

Es gibt mehrere Befehlszeilen - Dienstprogramme zu lösen Host - Namen ( host, dig, nslookup), aber sie verwenden alle Name - Server ausschließlich, während Anwendungen im Allgemeinen Blick in /etc/hostserste (mit gethostbyname glaube ich).

Gibt es ein Befehlszeilendienstprogramm, um Hostnamen aufzulösen, die sich wie eine normale Anwendung verhalten, also zuerst nachsehen /etc/hostsund dann erst einen Nameserver fragen?

(Mir ist bewusst, dass es wahrscheinlich 3 Zeilen von c sein würde, aber ich brauche es in einem etwas portablen Shell-Skript.)

Zulan
quelle
Können Sie uns bitte Ihre Situation etwas näher erläutern? Hilft das awk '/hostname/ { print $1 }' /etc/hosts?
Quanten
@quanta Tatsächlich ist die aktuelle Lösung grep / sed magic auf / etc / hosts. Ich wollte das mit einem Fallback verallgemeinern.
Zulan

Antworten:

56

Dies ist leicht zu erreichen mit getent:

getent hosts 127.0.0.1

getentsucht nach allen Arten von Daten, die in konfiguriert sind nsswitch.conf.

womble
quelle
Dies ist das Werkzeug, das ich in meinen Alpine Docker-Containern verwende, die keinen anderen Mechanismus wie digoder haben nslookup.
Bruno Bronosky
26

Ein Werkzeug, das funktionieren würde, ist getent. Sie könnten also getent hosts www.google.comoder verwenden getent hosts localhost. Es werden Einträge aus den Datenbanken abgerufen, die in Ihrer Name Service Switch-Konfiguration angegeben sind /etc/nsswitch.conf.

Zoredache
quelle
1
Ja, aber das würde nicht auf DNS zurückgreifen.
Slowpoison
Nein, es wird in der Reihenfolge nsswitch.conf aufgelöst.
cjc
@slowpoison, Schau dir deine nsswitch-Konfiguration an. Mein System hat files dnsfür Hosts, dh / etc / hosts wird abgefragt und dann der DNS-Resolver. Ihre Konfiguration kann unterschiedlich sein.
Zoredache
@ CJC, tut es. Ich glaube nicht, dass ich es richtig versucht habe.
Slowpoison
@Zoredache, ich bin ziemlich beeindruckt von getent. Vielen Dank für das Intro zu diesem Befehl.
Slowpoison
8

Sie können einen gethostbyname () (veralteten) Wrapper verwenden, wie:

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

Oder ein getaddrinfo () Wrapper wie:

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

Beachten Sie, dass getaddrinfo alle Instanzen als Liste zurückgibt. Der letzte Teil des Befehls wählt nur das erste Tupel aus. Dies kann auch IPv6-Adressen zurückgeben.

Mircea Vutcovici
quelle
1
Das wird funktionieren, ist aber schon eine Weile veraltet. Siehe linux.die.net/man/3/gethostbyname .
Kyle Smith
Danke, ich wusste es nicht. ;)
Mircea Vutcovici
Habe eine Gegenstimme. Es wurde kein anderer semi-portabler Einzeiler vorgeschlagen.
user239558
Falls dies für andere von Wert ist, habe ich eine Python 3-Version mit einigen Befehlszeilenoptionen erstellt: github.com/acdha/unix_tools/blob/master/bin/getaddrinfo
Chris Adams
6

resolveip werde dies tun.

Seltsamerweise ist es Teil der MySQL-Server-Pakete auf RHEL und Ubuntu.

cjc
quelle
6

Sie können [Ihre Lieblingssprache hier] verwenden, um ein Skript zu schreiben, das getnameinfo aufruft . So sollten Binärdateien (wie Ping) vorgehen, damit Sie die gleiche Behandlung erhalten.

Kyle Smith
quelle
6

Verwenden Sie getent ahostszum Beispiel:

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

Sie erhalten alle IPv4- und IPv6-Adressen über den glibc-Resolver (verwenden Sie also /etc/hostszuerst, wie normalerweise in konfiguriert /etc/nsswitch.conf).

Verwenden getent hostsSie diese Option nicht , da Sie entweder IPv6- oder IPv4-Adressen erhalten (nicht beide) und das ausgewählte Protokoll möglicherweise nicht funktioniert. In der Tat werden IPv6-Adressen im Allgemeinen bevorzugt, aber an einigen Stellen werden IPv6-Daten von den Routern gefiltert (nicht unterstützt).

vinc17
quelle
3

"gethostbyname" Kommandozeilen - Version :

#!/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
}
Erik Aronesty
quelle
2

Sie könnten wirklich hacky sein und Folgendes verwenden arp:

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

aber das wäre wirklich hässlich, also solltest du das nicht tun.

Paul M
quelle
2

getent hostsist kaputt. Es bevorzugt IPv6-Adressen, gai.confsollte so konfiguriert werden, dass es IPv4 bevorzugt, aber ...

Das Perl gethostbynameverwendet den Vorrang in/etc/nsswitch.conf

hosts: files dns

Das funktioniert also so, wie getent hostses für mich funktionieren sollte.

Ebenfalls:

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

sollte arbeiten.

Jan Wortelboer
quelle
5
Es ist nicht kaputt, es benutzt nur nicht getaddrinfo (welches /etc/gai.conf liest). Führen Sie Folgendes aus, um getaddrinfo zu verwenden getent ahosts.
craig65535
1

Versuche dies:

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
Quanten
quelle
-1

Der folgende Befehl führt eine Suche über DNS / etc / hosts über eine direkte DNS-Serversuche durch.

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

Mit diesem Befehl wird versucht, eine Domain (in diesem Fall google.com) einmal mit einer Wartezeit von 2 Sekunden zu pingen. Rufen Sie die erste Zeile des PING-Befehls ab, in der "PING google.com (216.58.199.36) 56 (84)" angegeben ist ) bytes of data ", dann verwenden Sie den Stream Editor (sed), um den ersten Satz von Klammern zu erkennen und die darin enthaltenen Daten zu extrahieren, bei denen es sich um die gesuchte IP-Adresse handelt.

HINWEIS: Der reguläre Ausdruck funktioniert nicht, wenn die URL Klammern (auch als runde Klammern bezeichnet) enthält. Dies ist jedoch ein seltener Fall.

John
quelle