Utilitário de linha de comando do Linux para resolver nomes de host usando / etc / hosts primeiro

36

Existem vários utilitários de linha de comando para nomes de host resolve ( host, dig, nslookup), no entanto, todos os servidores de nomes de uso exclusivamente, enquanto as aplicações em aparência geral em /etc/hostsprimeiro (utilizando gethostbyname eu acredito).

Existe um utilitário de linha de comando para resolver nomes de host que se comportam como um aplicativo comum, analisando /etc/hostsprimeiro e somente solicitando um servidor de nomes?

(Estou ciente de que provavelmente seria como 3 linhas de c, mas preciso dele dentro de um script shell um tanto portátil.)

Zulan
fonte
Poderia, por favor, explicar um pouco mais a sua situação? Será que awk '/hostname/ { print $1 }' /etc/hostsajuda?
quanta
@quanta Na verdade, a solução atual é grep / sed magic em / etc / hosts. Eu queria tornar isso mais geral com um recuo.
Zulan 22/08/11

Respostas:

56

Isso é facilmente alcançado com getent:

getent hosts 127.0.0.1

getentfará pesquisas para qualquer tipo de dados configurado no nsswitch.conf.

mulher
fonte
Essa é a ferramenta que eu uso nos meus contêineres Alpine Docker que não possuem outro mecanismo como digou nslookup.
Bruno311 # Bruno Bronosky
26

Uma ferramenta que funcionaria é getent. Então você pode usar getent hosts www.google.com, ou getent hosts localhost. Ele recuperará entradas dos bancos de dados, conforme especificado na sua configuração do Name Service Switch /etc/nsswitch.conf.

Zoredache
fonte
1
Sim, mas isso não recairia no DNS.
slowpoison
Não, ele resolve na ordem nsswitch.conf.
CJC
@slowpoison, dê uma olhada na sua configuração nsswitch. Meu sistema tem files dnspara hosts, o que significa que / etc / hosts é consultado e, em seguida, o resolvedor de DNS. Sua configuração pode ser diferente.
Zoredache
@cjc, ele faz. Eu não acho que tentei corretamente.
slowpoison
@ Zoredache, estou bastante impressionado getent. Obrigado pela introdução deste comando.
slowpoison
8

Você pode usar um wrapper gethostbyname () (descontinuado) como:

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

Ou um wrapper getaddrinfo () como:

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

Observe que getaddrinfo retornará todas as instâncias como uma lista. A última parte do comando seleciona apenas a primeira tupla. Isso também pode retornar endereços IPv6.

Mircea Vutcovici
fonte
1
Isso funcionará, mas está obsoleto há um tempo. Veja linux.die.net/man/3/gethostbyname .
Kyle Smith
Obrigado, eu não sabia disso. ;)
Mircea Vutcovici
Tenha um voto positivo. Nenhum outro liner semi-portátil foi proposto.
user239558
Caso isso seja de valor para qualquer outra pessoa, criei
Chris Adams
6

resolveip vai fazer isso.

Estranhamente, faz parte dos pacotes mysql-server no RHEL e Ubuntu.

cjc
fonte
6

Você pode usar [seu idioma favorito aqui] para escrever um script que chama getnameinfo . É assim que os binários (como ping) devem fazer isso, para garantir que você receba o mesmo tratamento.

Kyle Smith
fonte
6

Use getent ahosts, por exemplo:

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

Você obterá todos os endereços IPv4 e IPv6, através do resolvedor glibc (usando assim /etc/hostsprimeiro, como geralmente configurado em /etc/nsswitch.conf).

Não use getent hosts, pois ele fornecerá endereços IPv6 ou IPv4 (não ambos), e o protocolo escolhido pode não ser aquele que não funciona. De fato, os endereços IPv6 são geralmente preferidos, mas em alguns locais, os dados IPv6 são filtrados (não suportados) pelos roteadores.

vinc17
fonte
3

Versão da linha de comandos "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
fonte
2

Você pode ser realmente hacky e usar arp:

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

mas seria muito feio, então você não deve fazer isso.

Paul M
fonte
2

getent hostsestá quebrado. Prefere endereços IPv6, gai.confdeve ser configurado para preferir o ipv4, mas ....

O Perl gethostbynameusa a precedência em/etc/nsswitch.conf

hosts: files dns

Então, isso funciona como getent hostsdeve funcionar para mim.

Além disso:

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

Deveria trabalhar.

Jan Wortelboer
fonte
5
Não está quebrado, apenas não usa getaddrinfo (que lê /etc/gai.conf). Para usar o getaddrinfo, execute getent ahosts.
craig65535
1

Tente o seguinte:

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
quanta
fonte
-1

O comando a seguir executará a pesquisa via DNS / etc / hosts na pesquisa direta do servidor DNS.

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

Este comando tentará executar ping em um domínio (neste caso, google.com) uma vez com um tempo limite de espera de 2 segundos, obter a primeira linha do comando PING que indicará "PING google.com (216.58.199.36) 56 (84 ) bytes de dados ", use o Editor de Stream (sed) para detectar o primeiro conjunto de colchetes e extrair os dados nele, que é o endereço IP que estamos procurando.

NOTA: a expressão regex não funcionará se houver parênteses (também conhecido como colchetes circulares) na URL, mas esse seria um caso raro.

John
fonte