Утилита командной строки Linux для разрешения имен хостов с использованием / etc / hosts

36

Есть несколько утилит командной строки для имен решительности хозяв ( host, dig, nslookup), однако все они используют неймсерверы исключительно, в то время как приложения , в общем взгляде на /etc/hostsпервую ( с помощью gethostbyname я считаю).

Есть ли утилита командной строки для разрешения имен хостов, которая ведет себя как обычное приложение, таким образом, просматривая /etc/hostsсначала и только потом запрашивая сервер имен?

(Я знаю, что это, вероятно, будет как 3 строки c, но мне нужно это внутри несколько переносимого сценария оболочки.)

Zulan
источник
Не могли бы вы объяснить немного больше вашей ситуации? Помогает awk '/hostname/ { print $1 }' /etc/hosts?
Кванты
@quanta На самом деле текущим решением является grep / sed magic для / etc / hosts. Я хотел сделать это более общим с отступлением.
Зулан

Ответы:

56

Это легко достигается с помощью getent:

getent hosts 127.0.0.1

getentсделает поиск для любого типа данных, настроенных в nsswitch.conf.

ombble
источник
Это инструмент, который я использую в своих док-контейнерах Alpine, у которых нет другого механизма, такого как digили nslookup.
Бруно Броноски
26

Один инструмент, который будет работать, это getent. Так что вы можете использовать getent hosts www.google.com, или getent hosts localhost. Он будет извлекать записи из баз данных, как указано в конфигурации переключателя службы имен /etc/nsswitch.conf.

Zoredache
источник
1
Да, но это не откатится на DNS.
slowpoison
Нет, это разрешается в порядке nsswitch.conf.
CJC
@slowpoison, взгляни на свой конфиг nsswitch. В моей системе есть files dnsхосты, что означает обращение к / etc / hosts и затем преобразователь DNS. Ваш конфиг может быть другим.
Зоредаче
@cjc, это так. Я не думаю, что я попробовал это правильно.
slowpoison
@ Zoredache, я очень впечатлен getent. Спасибо за вступление к этой команде.
slowpoison
8

Вы можете использовать оболочку gethostbyname () (не рекомендуется), например:

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

Или оболочка getaddrinfo (), например:

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

Обратите внимание, что getaddrinfo вернет все экземпляры в виде списка. Последняя часть команды выбирает только первый кортеж. Это также может вернуть адреса IPv6.

Мирча Вуцовичи
источник
1
Это будет работать, но какое-то время устарело. Смотрите linux.die.net/man/3/gethostbyname .
Кайл Смит
Спасибо, я не знал об этом. ;)
Мирча Вутцовичи
Имейте upvote. Никаких других полупортативных однострочников не было предложено.
user239558
На случай, если это кому-нибудь пригодится, я сделал версию для Python 3 с несколькими параметрами командной строки: github.com/acdha/unix_tools/blob/master/bin/getaddrinfo
Крис Адамс,
6

resolveip сделаю это.

Как ни странно, это часть пакетов mysql-server на RHEL и Ubuntu.

CJC
источник
6

Вы можете использовать [ваш любимый язык здесь], чтобы написать скрипт, который вызывает getnameinfo . Именно так должны поступать двоичные файлы (например, ping), чтобы вы были уверены, что получаете то же лечение.

Кайл Смит
источник
6

Используйте getent ahosts, например:

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

Вы получите все адреса IPv4 и IPv6 через распознаватель glibc (таким образом, /etc/hostsсначала используйте , как обычно настраивается /etc/nsswitch.conf).

Не используйте getent hosts, так как он даст вам адреса IPv6 или IPv4 (не оба), и выбранный протокол может быть не тем, который не работает. Действительно, IPv6-адреса обычно предпочтительнее, но в некоторых местах данные IPv6 фильтруются (не поддерживаются) маршрутизаторами.

vinc17
источник
3

версия командной строки "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

Вы могли бы быть действительно взломаны и использовать arp:

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

но это было бы действительно ужасно, так что не стоит этого делать.

Пол М
источник
2

getent hostsсломан. Предпочитает IPv6-адреса, gai.confдолжен быть настроен на ipv4, но ....

Perl gethostbynameиспользует приоритет в/etc/nsswitch.conf

hosts: files dns

Так что это работает, как getent hostsдолжно работать для меня.

Также:

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

должно сработать.

Ян Вортелбор
источник
5
Он не сломан, он просто не использует getaddrinfo (который читает /etc/gai.conf). Чтобы использовать getaddrinfo, запустите getent ahosts.
craig65535
1

Попробуй это:

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

Следующая команда выполнит поиск через DNS / etc / hosts через прямой поиск DNS-сервера.

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

Эта команда попытается пропинговать домен (в данном случае google.com) один раз с тайм-аутом ожидания 2 секунды, получить первую строку команды PING, в которой будет указано «PING google.com (216.58.199.36) 56 (84). ) байтов данных ", затем с помощью Stream Editor (sed) определите первый набор скобок и извлеките в него данные, являющиеся искомым IP-адресом.

ПРИМЕЧАНИЕ: выражение regex не будет работать, если в URL есть круглые скобки (или круглые скобки), но это будет редкий случай.

Джон
источник