Как я могу разрешить имя хоста к IP-адресу в сценарии Bash?

Попробуйте цвета установки 256 явно в Вашем bashrc или zshrc:

export TERM=xterm-256color

или

export TERM=screen-256color

Если у Вас есть проблемы с tmux, не очищающим цвета фона правильно при использовании экранной установки термина, можно попробовать:

export TERM=screen-256color-bce
435
13.12.2015, 14:14
26 ответов

Можно использовать getent, который идет glibc (таким образом, у Вас почти наверняка есть он на Linux). Это разрешает использование gethostbyaddr/gethostbyname2 и так также проверит /etc/hosts/NIS/etc:

getent hosts unix.stackexchange.com | awk '{ print $1 }'

Или, как Heinzi заявил ниже, можно использовать dig с +short аргумент (запрашивает серверы DNS непосредственно, не смотрит на /etc/hosts/NSS/etc):

dig +short unix.stackexchange.com

Если dig +short недоступно, любое из следующего должно работать. Все они запрашивают DNS непосредственно и игнорируют другие средства разрешения:

host unix.stackexchange.com | awk '/has address/ { print $4 }'
nslookup unix.stackexchange.com | awk '/^Address: / { print $2 }'
dig unix.stackexchange.com | awk '/^;; ANSWER SECTION:$/ { getline ; print $5 }'

Если Вы хотите только распечатать один IP, то добавьте exit команда к awkрабочий процесс.

dig +short unix.stackexchange.com | awk '{ print ; exit }'
getent hosts unix.stackexchange.com | awk '{ print $1 ; exit }'
host unix.stackexchange.com | awk '/has address/ { print $4 ; exit }'
nslookup unix.stackexchange.com | awk '/^Address: / { print $2 ; exit }'
dig unix.stackexchange.com | awk '/^;; ANSWER SECTION:$/ { getline ; print $5 ; exit }'
560
27.01.2020, 19:28
  • 1
    По умолчанию, использование роют только работы с ipv4, где хост дает и ipv4 и ответы ipv6. Это могло бы быть неожиданно. Можно попробовать host www.google.com, dig +short www.google.com, host ipv6.google.com, dig +short ipv6.google.com, host www.facebook.com, dig +short www.facebook.com. –  jfg956 21.09.2011, 18:21
  • 2
    ВЫРОЙТЕ не работает, если будет CNAME, то он не возвратит IP. –  sorin 14.03.2014, 16:23
  • 3
    Иногда, host может быть приведен к таймауту и ничего не возвращает. Для некоторых доменов, dig +short может возвратить доменный псевдоним в первой строке. Так, гарантировать вывод - адрес IPv4, использовать dig +short example.com | grep -Eo '[0-9\.]{7,15}' | head -1. –  caiguanhao 07.06.2014, 18:25
  • 4
    Используя getent hosts <host> является неправильным, что касается примера, который это может привести адресу IPv6, в то время как IPv6 не работает. Правильное решение состоит в том, чтобы использовать getent ahosts <host> попробовать и IPv6 и IPv4 в случае необходимости. –  vinc17 03.10.2016, 18:02
  • 5
    Стоящий упоминания: разместите, выройте, и nslookup, кажется, непосредственно говорит с серверами, перечисленными в resolv.conf, тогда как "getent хосты" уважают и локальный файл hosts и кэширование уровня библиотеки (такое как nscd), если включено. –  Saustrup 12.06.2017, 14:59

Вы могли использовать host:

hostname=example.org

# strips the IP
IP=$( host ${hostname} | sed -e "s/.*\ //" )

# checks for errors
if [ $? -ne 0 ] ; then
   echo "Error: cannot resolve ${hostname}" 1>&2
   exit 1;
fi
5
27.01.2020, 19:28

Решения, данные до сих пор главным образом, работают в более простом случае: имя хоста непосредственно решает к единственному адресу IPv4. Это могло бы быть единственным случаем, где необходимо разрешить, что имена хостов, но в противном случае ниже обсуждение некоторых случаев, которые Вы, возможно, должны были бы обработать.

Chris Down и Heinzi кратко обсудили случай, где имя хоста решает больше чем к одному IP-адресу. В этом случае (и другие ниже), основные сценарии под предположением, что имя хоста непосредственно решает к единственному IP-адресу, могут повредиться. Ниже, пример с именем хоста, решающим к больше, чем единственный IP-адрес:

$ host www.l.google.com
www.l.google.com has address 209.85.148.147
www.l.google.com has address 209.85.148.103
www.l.google.com has address 209.85.148.99
www.l.google.com has address 209.85.148.106
www.l.google.com has address 209.85.148.105
www.l.google.com has address 209.85.148.104

Но что www.l.google.com? Это - то, где случай псевдонима должен быть представлен. Давайте проверим пример ниже:

$ host www.google.com
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 74.125.39.103
www.l.google.com has address 74.125.39.147
www.l.google.com has address 74.125.39.105
www.l.google.com has address 74.125.39.99
www.l.google.com has address 74.125.39.106
www.l.google.com has address 74.125.39.104

Так www.google.com непосредственно не решает к IP-адресам, но к псевдониму, который самому решает к нескольким IP-адресам. Для получения дополнительной информации о псевдонимах проверьте здесь. Конечно, случай, где псевдоним имеет единственный IP-адрес, возможен, как показано ниже:

$ host g.www.ms.akadns.net
g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net.
lb1.www.ms.akadns.net has address 207.46.19.190

Но псевдонимы могут быть объединены в цепочку? Ответ - да:

$ host www.microsoft.com
www.microsoft.com is an alias for toggle.www.ms.akadns.net.
toggle.www.ms.akadns.net is an alias for g.www.ms.akadns.net.
g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net.
lb1.www.ms.akadns.net has address 207.46.19.254

$ host www.google.fr
www.google.fr is an alias for www.google.com.
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 74.125.39.147
www.l.google.com has address 74.125.39.103
www.l.google.com has address 74.125.39.99
www.l.google.com has address 74.125.39.106
www.l.google.com has address 74.125.39.104
www.l.google.com has address 74.125.39.105

Я не нашел примера, где имя хоста решает к псевдониму, который не решает к IP-адресу, но я думаю, что случай мог бы произойти.

Больше, чем несколько IP-адресов и псевдонимов, там некоторые другие особые случаи... что относительно IPv6? Вы могли попробовать:

$ host ipv6.google.com
ipv6.google.com is an alias for ipv6.l.google.com.
ipv6.l.google.com has IPv6 address 2a00:1450:8007::68

Где имя хоста ipv6.google.com имя хоста только для IPv6. Что относительно имен хостов двойного стека:

$ host www.facebook.com
www.facebook.com has address 66.220.153.15
www.facebook.com has IPv6 address 2620:0:1c08:4000:face:b00c::

Снова о IPv6, если Вашим хостом является IPv4 только, можно все еще разрешить адреса IPv6 (протестированный на IPv4 только WinXP и с ipv6.google.com, Вы могли попробовать его на Linux). В этом случае разрешение успешно выполняется, но ping перестал работать с неизвестным сообщением об ошибке хоста. Это могло бы быть случаем, где Ваши сценарии перестали работать.

Я надеюсь, что те комментарии были полезны.

30
27.01.2020, 19:28
  • 1
    Какое большое дополнение к принятому ответу, показывая все пограничные случаи, что можно было бы хотеть иметь дело с в сценариях. Моя версия host даже не указывает, "имеет адрес" для моих полей. –  Mihai Danila 16.02.2013, 01:23

Следующее использование команды dig позволяет Вам читать результат непосредственно без любого sed/awk/etc. волшебства:

$ dig +short unix.stackexchange.com
64.34.119.12

dig также включен в dnsutils пакет.


Примечание: dig имеет возвращаемое значение 0, даже если имя не могло бы быть разрешено. Таким образом необходимо было бы проверить, пуст ли вывод вместо того, чтобы проверить возвращаемое значение:

hostname=unix.stackexchange.com

ip=`dig +short $hostname`

if [ -n "$ip" ]; then
    echo IP: $ip
else
    echo Could not resolve hostname.
fi

Примечание 2: Если имя хоста имеет несколько IP-адресов (попытка debian.org, например), все они будут возвращены. Эта "проблема" влияет на все инструменты, упомянутые в этом вопросе до сих пор:

45
27.01.2020, 19:28
  • 1
    Обратите внимание, что, если домен имеет запись CNAME, его домен может быть распечатан в первой строке вместо IP-адреса. ре –  pcworld 28.04.2018, 02:27

У меня есть инструмент на моей машине, которая, кажется, делает задание. Страница справочника показывает, что это, кажется, идет с mysql... Вот то, как Вы могли использовать его:

resolveip -s unix.stackexchange.com
64.34.119.12

Возвращаемое значение этого инструмента отличается от 0, если имя хоста не может быть разрешено:

resolveip -s unix.stackexchange.coma
resolveip: Unable to find hostid for 'unix.stackexchange.coma': host not found
exit 2

ОБНОВЛЕНИЕ На мягкой фетровой шляпе, это идет с mysql-сервером:

yum provides "*/resolveip"
mysql-server-5.5.10-2.fc15.x86_64 : The MySQL server and related files
Dépôt         : fedora
Correspondance depuis :
Nom de fichier      : /usr/bin/resolveip

Я предполагаю, что это создало бы странную зависимость для Вашего сценария...

56
27.01.2020, 19:28
  • 1
    Это, кажется, единственное решение на здесь, которое использует сборку ОС в сопоставителе - так работы для/etc/hosts, а также DNS. –  Gavin Brock 02.07.2012, 11:57
  • 2
    getent, как детализировано в другом ответе, также смотрит на/etc/hosts и идет с glibc, также - никакие зависимости от системы Linux. –  Asfand Qazi 16.04.2016, 16:32

С host от dnsutils пакета:

$ host unix.stackexchange.com
unix.stackexchange.com has address 64.34.119.12

(Исправленное имя пакета согласно комментариям. Как примечание другие дистрибутивы имеют host в различных пакетах: bind9-хост Debian/Ubuntu, openSUSE связывает-utils, Frugalware связывают.)

142
27.01.2020, 19:28
  • 1
    Вы имели в виду dnsutils? Так или иначе, host обработанный хороший, спасибо –  Eugene Yarmash 15.09.2011, 17:55
  • 2
    Вы, вероятно, правы. У меня нет Arch здесь для проверки. (Предназначенный для добавления комментария, позже упомянув это, но ответ уже был upvoted, таким образом, я предположил, что закрепил его...) –  manatwork 15.09.2011, 18:06
  • 3
    Посмотрите resolveip запись ниже, если необходимо разрешить что-то не в DNS (например,/etc/hosts) –  Gavin Brock 02.07.2012, 11:56
  • 4
    знать это host иногда вывод мультилинии возвратов (в случае перенаправлений), Вы захотите host unix.stackexchange.com | tail -n1 если Вы просто хотите строку с IP-адресом. –  Edward Coffey 23.01.2013, 07:04
  • 5
    Этот ответ заслуживает серьезного downvote. host инструмент DNS (подобный nslookup) таким образом, это только ищет хосты в DNS, не в, например. /etc/hosts. Таким образом, это не ответ на вопрос OP. –  peterh 11.09.2014, 12:49
ping -q -c 1 -t 1 your_host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"

работы без зависимостей от других систем (и для хостов, указанных в/etc/hosts)

19
27.01.2020, 19:28
  • 1
    Использование ping - то, в чем я нуждался, как мне нужно значение от файла hosts, но sed шаблона, анализирующего правильно, но этого обработанного-q-c 1-t 1 your_host_here ping | grep PING | sed-e "s/^ [^ (] * [(]//" | sed-e "s / [)].* $//" –  ManiacZX 18.01.2013, 21:23
  • 2
    Для разрешения чего-то в моей домашней сети как myhostname.local, это работает так на меня, это - лучший ответ. –  Matt Friedman 24.01.2015, 04:59
  • 3
    Позвольте мне предложить это также: ping -q -c 1 -t 1 bahface.local | grep -m 1 PING | cut -d "(" -f2 | cut -d ")" -f1 –  Matt Friedman 24.01.2015, 05:08
  • 4
    getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname> работы для объявлений внутри /etc/hosts, также... и это - дежурный инструмент для всех видов системных баз данных (passwd, группа, псевдонимы, сервисы). –  0xC0000022L 30.04.2015, 10:53

Избегать проблемы с псевдонимами и всегда получать единственный готовый к употреблению IP-адрес:

python -c 'import socket; print socket.gethostbyname("www.example.com")'
22
27.01.2020, 19:28

Вот небольшое изменение ping подход, который принимает во внимание "неизвестный хост" (путем передачи по каналу через stderr) и использование tr избегать использования sed regexps:

ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d '():' | awk '/^PING/{print $3}'

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

ping -c1 -t1 -W0 www.example.com &>/dev/null && ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d '():' | awk '/^PING/{print $3}'
8
27.01.2020, 19:28
getent hosts unix.stackexchange.com | cut -d' ' -f1
42
27.01.2020, 19:28
  • 1
    Также рассмотрите ahosts, ahostsv4, ahostsv6 с getent. –  0xC0000022L 30.04.2015, 01:12
  • 2
    cut не будет для getent's, которые используют \t разделить столбцы. Дело обстоит так на Солярисе. –  ceving 18.03.2016, 11:51
  • 3
    @ceving: На Солярисе Вам, возможно, придется работать cut без -d (значения по умолчанию к \t как разделитель). На Linux это - пробелы, таким образом строка выше работ. –  sborsky 08.04.2016, 01:24

вот рецепт Bash, который я приготовил, использование ответов другого народа — сначала пробует /etc/hosts, затем отступает к nslookup:

resolveip(){
    local host="$1"
    if [ -z "$host" ]
    then
        return 1
    else
        local ip=$( getent hosts "$host" | awk '{print $1}' )
        if [ -z "$ip" ] 
        then
            ip=$( dig +short "$host" )
            if [ -z "$ip" ]
            then
                echo "unable to resolve '$host'" >&2 
                return 1
            else
                echo "$ip"
                return 0
            fi
        else
            echo "$ip"
            return 0
        fi
    fi
}
5
27.01.2020, 19:28
  • 1
    Быть ясным, getent hosts не просто поиск в/etc/hosts - это - настоящий разрешающий DNS вызов к gethostbyaddr (3), и он очень вряд ли перестанет работать в случае где dig успешно выполнится. См. страницу справочника для getent. –  Stuart P. Bentley 03.08.2014, 14:42
  • 2
    @Stuart является правильным — я изучил много начиная с записи, что и упростили мощную команду. getent остается моим фаворитом, хотя мне также нравится dig +short –  RubyTuesdayDONO 03.08.2014, 21:26

Простой, но полезныйl:

  1. getent ahostsv4 www.google.de | grep grep STREAM | head -n 1 | cut -d ' -f 1
  2. getent ahostsv6 www.google. de | grep STREAM | head -n 1 | cut -d '' -f 1
  3. getent hosts google.de | head -n 1 | cut -d '' -f 1

Все команды будут разрешать IP-адрес, если хост все еще существует. Если хост указывает на CNAME, он также получит IP-адрес в этом случае.

Первая команда возвращает разрешенный IPv4-адрес

Вторая команда возвращает разрешенный IPv6-адрес

Третья команда возвращает владельцу предпочтительный адрес, который может быть IPv4 или IPv6-адресом.

.
19
27.01.2020, 19:28

Чтобы завершить ответ Криса Дауна и ответить на комментарии jfgagne о (возможно связанных) псевдонимах, вот решение, которое:

  • учитывает несколько IP-адресов
  • учитывает один или несколько псевдонимы (CNAME)
  • не запрашивают файл / etc / hosts (в моем случае он мне не нужен); для его запроса решение dbernt на Python идеально)
  • не использует awk / sed

     dig + short www.alias.com |  grep -v "\. $" |  голова -n 1
     

Всегда возвращает первый IP-адрес или пустую строку, если не разрешено. с версией раскопок:

    $ dig -v
    DiG 9.8.1-P1
8
27.01.2020, 19:28
 php -r "echo gethostbyname('unix.stackexchange.com');"
6
27.01.2020, 19:28
nmap -sP 192.168.178.0/24|grep YOUR_HOSTNAME|sed -n 's/.*[(]\([0-9\.]*\)[)].*/\1/p'

было найдено решение без DNS-сервера

.
5
27.01.2020, 19:28

Может быть, не самый краткий, но кажется надежным и эффективным:

# $(get_host_dns_short "google.com")
#
# Outputs the IPv4 IP Address of a hostname, resolved by DNS. Returns 0 if DNS
# responded successfully; 1 otherwise. Will mask error output.
function get_host_dns_short()
{
    (
        set -o pipefail

        host -4 -W1 -t A "$1" 2>/dev/null | awk '/has address/ { print $NF; exit }'
    ) && return 0 || return 1
}

Это выведет один IPv4 IP, а также вернет 1 в случае сбоя при маскировании вывода stderr.

Вы можете использовать его так:

GOOGLE_IP="$(get_host_dns_short "google.com")"
if [[ $? -eq 0 ]]; then
    echo "Google's IP is ${GOOGLE_IP}."
else
    echo "Failed to resolve Google's IP."
fi

IP-адрес Google - 216.58.192.46.

Если вместо этого вам нужен IPv6-адрес, просто замените -4 на -6 .

4
27.01.2020, 19:28

dig +noall +answer +nocomments example.com | awk '{printf "%-36s\t%s\n", $1, $5 }'

4
27.01.2020, 19:28

Я хотел бы добавить это в качестве комментария к Эндрю МакГрегору Re: ping. Однако это не позволило мне, поэтому мне нужно добавить это как еще один ответ. (Если кто-то может переместить его в комментарий, не стесняйтесь.)

Это еще один вариант, только с использованием ping и grep:

ping -q -c1 -t1 your_host_here | grep -Eo "([0-9]+\.?){4}"

grep -E для расширенного регулярного выражения и ] grep -o , чтобы вернуть только соответствующую часть. само регулярное выражение ищет одну или несколько цифр ( [0-9] + ) и, необязательно, точку ( \.? ) четыре раза ( {4} )

6
27.01.2020, 19:28

Я постоянно делаю это на своем Mac, на котором нет getent. ping выглядит как взлом.Я также хотел бы принять во внимание /etc/hosts.

Итак, я написал дурацкую оболочку для dns.lookup для тех, у кого установлен Node.js, чтобы предоставить интерфейс командной строки:

$ npm install -g lookup-hostname
$ lookup google.com
62.243.192.89
4
27.01.2020, 19:28

1 строка разрешает список имен хостов

for LINE in `cat ~/Desktop/mylist`; do a=$(nslookup $LINE | awk '/^Address: / { print $1 }');  echo $a >> ~/Desktop/ip; done
3
27.01.2020, 19:28

dig работает слишком медленно, nslookup намного быстрее

nslookup google.com | grep -Po 'Address:\s*[0-9.]+' | tail -1 | sed -e 's/Address:\s*//g'
5
27.01.2020, 19:28
host -t a cisco.com

эта команда покажет IP-адрес (переадресует домен на IP-адрес)

-1
27.01.2020, 19:28

Да, ответов уже много, но решения с использованием perl нет:

perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com

В сценарии bash это можно было бы использовать так:

#!/bin/bash
ipaddr=$(perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com)
echo $ipaddr

Модули, используемые здесь, являются базовыми модулями, поэтому они должны быть доступны везде без установки с помощью CPAN.

2
27.01.2020, 19:28
#!/bin/bash

systemd-resolve   RT.com -t A  | awk '{ print $4 ; exit }'
systemd-resolve unix.stackexchange.com -t A --legend=no | awk '{ print $4 ; exit }'

resolveip -s      RT.com
dig       +short  RT.com
host              RT.com | awk '/has address/ { print $4 }'
nslookup          RT.com | awk '/^Address: /  { print $2 }'
ping -q -c 1 -t 1 RT.com | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"

ruby     -rresolv -e      ' print    Resolv.getaddress "RT.com" '
python2  -c 'import socket; print socket.gethostbyname("RT.com")'
perl     -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' RT.com  2>/dev/null
php      -r "echo gethostbyname( 'RT.com' );"

echo        "   all do work for me - take your pick!  "
2
27.01.2020, 19:28

Помимо приведенного выше решения, вы можете преобразовать несколько имен хостов в IP с помощью приведенного ниже сценария, единственной зависимостью является команда «ping» в ядре Unix:

getip(){ ping -c 1 -t 1 $1 | head -1 | cut -d ' ' -f 3 | tr -d '()' 2>&1 | tee >> /tmp/result.log & }

getip 'hostname.number1.net'

getip 'hostname.number2.net'

getip 'hostname.number3.net'

getip 'hostname.number4.net'

getip 'hostname.number5.net'

getip 'hostname.number6.net'

getip 'hostname.number7.net'

getip 'hostname.number8.net'
$ cat /tmp/result.log

ABC.DEF.GHI.XY1

ABC.DEF.GHI.XY2

ABC.DEF.GHI.XY3

ABC.DEF.GHI.XY4

ABC.DEF.GHI.XY5

ABC.DEF.GHI.XY6

ABC.DEF.GHI.XY7

ABC.DEF.GHI.XY8

-1
27.01.2020, 19:28

Вариант на основе python3, отображающий все адреса ipv4 и ipv6 из DNS-преобразователя системы, каждый ip в виде отдельной строки:

python3 -c 'import socket, sys; print("\n".join([x[4][0] for x in socket.getaddrinfo(sys.argv[1], 0, type=socket.SocketKind.SOCK_STREAM)]))' example.com

Если требуется разумная обработка ошибок, потребуется дополнительный блок try :и т. д.

0
03.03.2021, 08:45

Теги

Похожие вопросы