web-dev-qa-db-ja.com

Bashスクリプトでホスト名をIPアドレスに解決するにはどうすればよいですか?

Bashスクリプトでホスト名をIPアドレスに解決する最も簡潔な方法は何ですか? Arch Linux を使用しています。

450
Eugene Yarmash

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 }'

1つの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 }'
570
Chris Down

dnsutils パッケージのHostを使用:

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

コメントに従って修正パッケージ名。注記として、他のディストリビューションは異なるパッケージにHostを持っています:Debian/Ubuntubind9-Host、openSUSEbind-utils、Frugalwarebind

146
manatwork

私のマシンには、その仕事をしているように見えるツールがあります。マニュアルページには、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

[〜#〜] update [〜#〜] Fedoraでは、mysql-serverが付属しています:

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
greg0ire

Digを使用する次のコマンドを使用すると、sed/awk/etcなしで結果を直接読み取ることができます。マジック:

$ Dig +short unix.stackexchange.com
64.34.119.12

Digdnsutilsパッケージに含まれています。


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
Heinzi
getent hosts unix.stackexchange.com | cut -d' ' -f1
44
sborsky

これまでの解決策は、主に単純なケースで機能します。ホスト名は単一の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?これは、aliasケースを導入する必要がある場所です。以下の例を確認してみましょう。

$ 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はunknown Hostエラーメッセージで失敗します。これは、スクリプトが失敗する場合です。

これらのコメントがお役に立てば幸いです。

30
jfg956

エイリアスの問題を回避し、常に単一のIPアドレスを使用できるようにするには:

python -c 'import socket; print socket.gethostbyname("www.example.com")'
22
dbernt

シンプルだが便利:

  1. getent ahostsv4 www.google.de | 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アドレスを返します

2番目のコマンドは、解決されたIPv6アドレスを返します

3番目のコマンドは、所有者の優先アドレスであるIPv4またはIPv6アドレスを返します。

19
Tom Freudenberg
ping -q -c 1 -t 1 your_Host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"

他のシステムに依存せずに動作します(および/ etc/hostsで指定されたホストに対して)

19
Andrew McGregor

これは、「未知のホスト」を考慮に入れて(stderrを介してパイプすることにより)pingアプローチのわずかなバリエーションであり、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}'
9
Stefan Farestam

Chris Downの回答を完了し、(おそらくチェーン化されている)エイリアスに関するjfgagneコメントに対処するためのソリューションは次のとおりです。

  • 複数のIPを考慮に入れる
  • 1つ以上のエイリアスを考慮します(CNAME)
  • クエリしない/etc/hostsファイル(私の場合、私はそれを望まなかった);それを照会するには、dberntのpython解が完璧です)
  • awk/sedを使用しない

    Dig +short www.alias.com  | grep -v "\.$" | head -n 1
    

常に最初のIPアドレスを返すか、解決されない場合は空のトレースを返します。 Digのバージョン:

    $ Dig -v
    Dig 9.8.1-P1
8
Franck
 php -r "echo gethostbyname('unix.stackexchange.com');"
6
Mohammed Zourob

Andrew McGregor Re:pingへのコメントとしてこれを追加したいと思います。しかし、それは私には許されないので、これを別の答えとして追加する必要があります。 (誰かがコメントに移動できる場合は、遠慮なくご利用ください。)

これは別のバリアントで、pingとgrepのみを使用しています。

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

grep -E拡張正規表現およびgrep -oは、一致する部分のみを返します。正規表現自体が1桁または複数桁([0-9]+)およびオプションでドット(\.?) 四回 ({4}

6
Dweia
nmap -sP 192.168.178.0/24|grep YOUR_HOSTNAME|sed -n 's/.*[(]\([0-9\.]*\)[)].*/\1/p'

dNSサーバーなしで私が見つけた解決策でした

5

ここに私が他の人々の答えを使って調理したバッシュのレシピがあります—最初の試み/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
RubyTuesdayDONO

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
Matteo

多分最も簡潔ではないかもしれませんが、堅牢で効率的です:

# $(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を出力するだけでなく、stderr出力をマスクしながら、障害が発生した場合に1を返します。

次のように使用できます。

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

GoogleのIPは216.58.192.46です。

代わりにIPv6アドレスが必要な場合は、-4-6に置き換えてください。

4
Will

Digが遅すぎる、nslookupがはるかに速い

nslookup google.com | grep -Po 'Address:\s*[0-9.]+' | tail -1 | sed -e 's/Address:\s*//g'
4
Andrey Izman

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

4
D P Baker

1行でホスト名のリストを解決します

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

Bashスクリプトの最も簡単な方法はわかりませんが、ホスト名を解決してホストが稼働しているかどうかを確認するには、ping!を使用します。

ping -a hostname -c 1

ホストをpingして、ホスト名をIPアドレスに解決します。

$ ping -a www.google.com -c 1
PING www.google.com (216.58.211.132) 56(84) bytes of data.
64 bytes from arn09s10-in-f4.1e100.net (216.58.211.132): icmp_seq=1 ttl=54 time=1.51 ms
3
user257655

私はgetentがないMacでいつもこれをやっています。 pingはハックのようです。 /etc/hostsも考慮に入れたいと思います。

したがって、Node.jsをインストールしてCLIを提供するユーザー向けに、dns.lookupの愚かなラッパーを作成しました。

$ npm install -g lookup-hostname
$ lookup google.com
62.243.192.89
3
Thomas Jensen
#!/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
dotbit

はい、すでに多くの回答がありますが、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
Slaven Rezic