Narzędzie wiersza poleceń systemu Linux do rozwiązywania nazw hostów za pomocą / etc / hosts

36

Istnieje kilka narzędzi wiersza polecenia do nazw hostów resolve ( host, dig, nslookup), jednak są one wszystkie serwery nazw użytku wyłącznie, gdy aplikacje w ogólnym wyglądzie w /etc/hostspierwszym (używając gethostbyname wierzę).

Czy istnieje narzędzie wiersza polecenia do rozpoznawania nazw hostów, które zachowują się jak zwykła aplikacja, a więc szukają /etc/hostsnajpierw, a dopiero potem pytają serwer nazw?

(Zdaję sobie sprawę, że prawdopodobnie byłyby to 3 wiersze c, ale potrzebuję go w dość przenośnym skrypcie powłoki).

Zulan
źródło
Czy mógłbyś bardziej wyjaśnić swoją sytuację? Czy awk '/hostname/ { print $1 }' /etc/hostspomaga
kwanty
@quanta Właściwie obecne rozwiązanie to grep / sed magic na / etc / hosts. Chciałem uczynić to bardziej ogólnym z rezerwą.
Zulan

Odpowiedzi:

56

Można to łatwo osiągnąć dzięki getent:

getent hosts 127.0.0.1

getentwykona wyszukiwania dla dowolnego typu danych skonfigurowanych w nsswitch.conf.

womble
źródło
To narzędzie, którego używam w moich kontenerach dokujących Alpine, które nie mają innego mechanizmu, takiego jak diglub nslookup.
Bruno Bronosky
26

Jednym z narzędzi, które by działało, jest getent. Więc możesz użyć getent hosts www.google.comlub getent hosts localhost. Pobiera wpisy z baz danych zgodnie z konfiguracją przełącznika usługi nazw /etc/nsswitch.conf.

Zoredache
źródło
1
Tak, ale to nie spadnie na DNS.
slowpoison
Nie, rozwiązuje to w kolejności nsswitch.conf.
cjc
@slowpoison, spójrz na swoją konfigurację nsswitch. Mój system ma files dnsdla hostów, co oznacza, że ​​sprawdzany jest plik / etc / hosts, a następnie resolver DNS. Twoja konfiguracja może być inna.
Zoredache,
@cjc to robi. Nie sądzę, że wypróbowałem to poprawnie.
slowpoison
@Zoredache, jestem pod wrażeniem getent. Dzięki za wprowadzenie do tego polecenia.
slowpoison
8

Możesz użyć opakowania gethostbyname () (przestarzałe), takiego jak:

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

Lub opakowanie getaddrinfo (), takie jak:

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

Zauważ, że getaddrinfo zwróci wszystkie instancje jako listę. Ostatnia część polecenia wybiera tylko pierwszą krotkę. Może to również zwrócić adresy IPv6.

Mircea Vutcovici
źródło
1
To zadziała, ale przez jakiś czas było przestarzałe. Zobacz linux.die.net/man/3/gethostbyname .
Kyle Smith
Dziękuję, nie wiedziałem o tym. ;)
Mircea Vutcovici
Zyskaj głos. Nie zaproponowano żadnej innej półprzenośnej jednowarstwowej.
user239558
Na wypadek, gdyby miało to wartość dla kogokolwiek innego, stworzyłem wersję Python 3 z kilkoma opcjami wiersza poleceń: github.com/acdha/unix_tools/blob/master/bin/getaddrinfo
Chris Adams
6

resolveip zrobi to.

Co dziwne, jest to część pakietów mysql-server na RHEL i Ubuntu.

cjc
źródło
6

Możesz użyć [swojego ulubionego języka tutaj], aby napisać skrypt, który wywołuje getnameinfo . W ten sposób powinny to robić pliki binarne (takie jak ping), więc masz pewność, że otrzymasz takie samo traktowanie.

Kyle Smith
źródło
6

Użyj getent ahostsna przykład:

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

Otrzymasz wszystkie adresy IPv4 i IPv6, za pośrednictwem programu rozpoznawania nazw glibc (w ten sposób używając /etc/hostspierwszego, jak zwykle skonfigurowanego w /etc/nsswitch.conf).

Nie używaj getent hosts, ponieważ da ci to adresy IPv6 lub IPv4 (nie oba), a wybrany protokół może nie być tym, który nie działa. Rzeczywiście, adresy IPv6 są ogólnie preferowane, ale w niektórych miejscach routery filtrują (nie są obsługiwane) dane IPv6.

vinc17
źródło
3

Wersja wiersza polecenia „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
}
Erik Aronesty
źródło
2

Możesz być naprawdę hacky i użyć arp:

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

ale byłoby to naprawdę brzydkie, więc nie powinieneś tego robić.

Paul M.
źródło
2

getent hostsjest zepsuta. Preferuje adresy IPv6, gai.confpowinien być skonfigurowany tak, aby preferował IPv4, ale ....

Perl gethostbynameużywa pierwszeństwa w/etc/nsswitch.conf

hosts: files dns

Więc to działa jak getent hostspowinno działać dla mnie.

Również:

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

powinno działać.

Jan Wortelboer
źródło
5
Nie jest zepsuty, po prostu nie używa getaddrinfo (który czyta /etc/gai.conf). Aby użyć getaddrinfo, uruchom getent ahosts.
craig65535,
1

Spróbuj tego:

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
kwanty
źródło
-1

Następujące polecenie wykona wyszukiwanie przez DNS / etc / hosts przez bezpośrednie wyszukiwanie serwera DNS.

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

To polecenie spróbuje wysłać polecenie ping do domeny (w tym przypadku google.com) jeden raz z czasem oczekiwania wynoszącym 2 sekundy, pobierz pierwszy wiersz polecenia PING, który będzie oznaczać „PING google.com (216.58.199.36) 56 (84 ) bajtów danych ”, a następnie użyj Edytora strumienia (sed), aby wykryć pierwszy zestaw nawiasów i wyodrębnić w nim dane, których szukamy.

UWAGA: wyrażenie regularne nie będzie działać, jeśli w adresie URL znajdują się nawiasy (zwane również nawiasami okrągłymi), ale byłby to rzadki przypadek.

Jan
źródło