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


416

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


21
getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname>答えが下の近くのどこかにあるのは残念です。これは最も単純で、追加のパッケージを必要とせず、Bashスクリプトからも解析が簡単です。
0xC0000022L

1
@ 0xC0000022L:新しい恥は、その答えは示唆していることであるgetent hosts somehostとき、この実行中にしばらく時間がsomehost IPv6アドレスを生成します他のほとんどのツールは、(どのように異なっている、pingssh少なくとも)名前を解決し、そしていくつかのものを壊します。のahosts代わりにを使用してくださいhosts
j_random_hacker

@j_random_hacker:誰がIPv4(ahostsv4または IPv6(ahostsv6)アドレスを特別にリクエストしないようにしますか?個人的には、IPv6を返す不特定のリクエストに問題はありません。コードを準備する必要があります。IPv6は20年以上前から存在しています。
0xC0000022L

@ 0xC0000022L:誰もそれを「嫌う」ことはありませんが、答えは具体的に示唆しhosts、これまでに4人が「突然IPv6」によって引き起こされる痛みを表現するvinc17のコメントを支持しています。IPv6の準備が常に問題になるわけではありません。多くのプログラムには、2つの名前/アドレスが同じホストを参照しているかどうかを判断する方法が必要です。単純な文字列照合を使用するか、ネットワークについて多くの知識を持っている必要があります。後者は地雷原であるため、多くのサードパーティのプログラムとシステム(私が制御することはできません)は前者を使用しています。
j_random_hacker

回答:


533

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

2
デフォルトでは、digの使用は、ホストがipv4とipv6の両方の回答を提供するipv4でのみ機能します。これは予想外のことかもしれません。あなたは試すことができhost www.google.comdig +short www.google.comhost ipv6.google.comdig +short ipv6.google.comhost www.facebook.comdig +short www.facebook.com
jfg956

6
DIGは機能しません。CNAMEの場合、IPは返されません。
ソリン

4
時々、hostタイムアウトになり、何も返されません。ドメインによってdig +shortは、最初の行にドメインエイリアスを返す場合があります。したがって、出力がIPv4アドレスであることを確認するには、を使用しますdig +short example.com | grep -Eo '[0-9\.]{7,15}' | head -1
caiguanhao 14年

9
使用getent hosts <host>は正しくありません。たとえば、IPv6が機能しない間はIPv6アドレスを提供する可能性があります。正しい解決策はgetent ahosts <host>、必要に応じてIPv6とIPv4の両方を試すために使用することです。
vinc17

5
言及する価値があります:host、dig、nslookupはresolv.confにリストされているサーバーと直接通信しているようですが、「getent hosts」はローカルホストファイルとライブラリレベルキャッシュ(nscdなど)の両方を有効にします。
ザウストラップ

141

以下とhostからdnsutilsのパッケージ:

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

(コメントに従ってパッケージ名を修正しました。注記として、他のディストリビューションにhostは異なるパッケージがあります:Debian / Ubuntu bind9-host、openSUSE bind-utils、Frugalware bind。)


4
もしかしてdnsutilsを?とにかく、hostうまく
いきました

あなたはおそらく正しいです。チェックするアーチはありません。(後でこれについて言及するコメントを追加するつもりでしたが、答えはすでに支持されていたので、私はそれを打ち込んだと思います...)
manatwork

1
(たとえば、/ etc / hostsに)あなたがいないDNSで何かを解決する必要がある場合は、以下のresolveipにエントリを参照してください
ギャビンBrockの

2
host時々複数行の出力を返すことに注意してください(リダイレクトの場合)host unix.stackexchange.com | tail -n1。IPアドレスのある行だけが必要な場合があります。
エドワードコフィー

3
この答えは深刻な下票に値する。hostはDNSツールで(に似nslookupています)、DNSではなくDNS内のホストのみを検索します/etc/hosts。したがって、OPの質問に対する答えではありません
ペテル14

54

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

更新 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

私はあなたのスクリプトに奇妙な依存関係を作成すると思います...


6
これは、OSのビルドリゾルバを使用するここでの唯一の解決策であるようです。したがって、/ etc / hostsとDNSで機能します。
ギャビンブロック

8
getent、他の回答で詳しく説明されているように、/ etc / hostsも参照し、glibcが付属しているため、Linuxシステムに依存しません。
Asfand Qazi

44

次のコマンドを使用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たとえば、try )、それらすべてが返されます。この「問題」は、これまでこの質問で言及されたすべてのツールに影響します。


2
ドメインにCNAMEエントリがある場合、そのドメインはIPアドレスの代わりに最初の行に印刷される場合があることに注意してください。
pcworld

40
getent hosts unix.stackexchange.com | cut -d' ' -f1

4
また検討しahostsahostsv4ahostsv6getent
-0xC0000022L

cut\t列を区切るgetentには使用しません。これは、Solarisの場合です。
16年

1
@ceving:Solarisでは、cutなしで実行する必要がある場合があります-d(デフォルト\tはdelimiterになります)。Linuxではスペースなので、上記の行が機能します。
-sborsky

27

これまでに説明したソリューションは、ほとんど単純なケースで機能します。ホスト名は、単一の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::

繰り返しになりますが、ホストがIPv4のみの場合、IPv6アドレスを解決できます(IPv4のみのWinXPでテストし、ipv6.google.comでテストすると、Linuxで試すことができます)。この場合、解決は成功しますが、pingは失敗し、不明なホストエラーメッセージが表示されます。これは、スクリプトが失敗する場合があります。

これらの発言が役に立つことを願っています。


2
スクリプティングで対処したいすべてのエッジケースを示す、受け入れられた答えを補完するものです。私のバージョンでhostは、ボックスの「アドレスを持っています」とさえ表示されません。
ミハイダニラ


18
ping -q -c 1 -t 1 your_host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"

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


2
pingの使用は、hostsファイルからの値が必要なのに必要なものですが、sedパターンは正しく解析されますが、これはping -q -c 1 -t 1 your_host_here | grep PING | sed -e "s / ^ [^(] * [(] //" | sed -e "s /[)].*$//"
ManiacZX

1
myhostname.localのような私のホームネットワーク上の何かを解決するためにこれは機能するので、私にとってこれが最良の答えです。
マットフリードマン

1
また、私はこれを提案することができる:ping -q -c 1 -t 1 bahface.local | grep -m 1 PING | cut -d "(" -f2 | cut -d ")" -f1
マット・フリードマン

getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname>内部の宣言のために働く/etc/hosts、あまりにも...それはだシステムデータベース(passwdファイル、グループ、エイリアス、サービス)のすべての種類の行くツーツール。
0xC0000022L

17

シンプルだが便利:

  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アドレス)を返します。


はるかに単純なものです。そして、デフォルトで利用可能です。それが好きhostではないのインストールが必要ですbindutils
michaelbn

7

ping「未知のホスト」を考慮に入れた(stderrを経由する)アプローチのわずかなバリエーションがあり、正規表現の使用trを回避するために使用されますsed

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

このソリューションは、追加のツールなしで機能するため気に入っています。
ラドン8472

7

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

1
おかげで、他の答えは「dig + short」が常に単一のIPアドレスを返すと仮定しています。彼らはCNAMEを考慮していませんでした。
ジャムシッド


5

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回({4})探します


4

以下を使用できます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

4

他の人々の答えを使用して作成した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
}

明確にするために、getent hosts/ etc / hostsの中だけのルックアップではありません-それは、フルにDNS-解決コールするのです(3)のgethostbyaddr、それはだ非常の場合に失敗する可能性は低いdig成功します。getentのマニュアルページを参照してください
スチュアートP.ベントレー14

@Stuartは正しい—私はそれを書いてから多くのことを学び、強力なコマンドを単純化しすぎた。getent私も好きなものの、私のお気に入りは、残っているdig +short
RubyTuesdayDONO


3

おそらく最も簡潔ではありませんが、堅牢で効率的なようです:

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

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

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


3

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


1
既存の回答よりもその回答がどのように改善されるのか、いくつかのコンテキストは素晴らしいでしょう。また、コマンドを4スペース分インデントしてください(マークダウン構文を参照)。
maxschlepzig

2

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

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

2

持っていないMacでこれを常に行っていますgetentpingハックのようです。私/etc/hostsも考慮したいと思います。

そこで、dns.lookupCLIを提供するNode.jsがインストールされているあなたのために、私は愚かなラッパーを書きました。

$ npm install -g lookup-hostname
$ lookup google.com
62.243.192.89

解決に近づく前に60%の確率で破損する。
ドットビット

@dotbitを詳しく説明してもらえますか?私は17年以来、これを毎週使用しており、問題はありませんでした。
トーマスジェンセン

@Jensenでも、いつものようにあなたはあなただけです。私たちの残りの部分は、通常、ある種または別の種類のFAILに常に遭遇します。
ドットビット

「いつものように」それはどういう意味ですか? 「私たちの残り」それは誰ですか? 「FAILにぶつかる」どのような具体的な問題が発生していますか?私は興味がある。
トーマスジェンセン


2

bashスクリプトの最も簡単な方法はわかりませんが、ホスト名を解決してホストが起動しているかどうかを確認したい場合は、ping

ping -a hostname -c 1

ウィルpingホスト1時間と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

pingを使用するのは良いことです。誰もがそれを持っているからですが、スクリプトで使用したい場合は、出力からIPパーツをフィルターする必要があります。
ラドン8472

1

はい、すでに多くの答えがありますが、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を使用してインストールしなくてもどこでも使用できます。


perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com 2>/dev/null ずっときれいです。しかし、私たち2人以外は誰もpörlを使用していません。他の人はもちろんPascalスクリプトを使用しています。
ドットビット

実際、何か問題が発生した場合は、エラーメッセージを表示することを好みます。Can't call method "addr" on an undefined value正確なエラーメッセージではありませんが、問題に関するヒントを提供する場合があります。
レイヴンレジック

1
#!/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!  "

1
rubyバージョンはIPアドレスの周りに引用符を出力します---おそらくのprint代わりに使用する必要がありpます。
Slaven Rezic

thx、@ Slaven Rezic、お気軽に投票してください。再び、ここの一番下にあるスクリプトは実際にもっと見えるかもしれません... ;-)
dotbit

-1
host -t a cisco.com

このコマンドはIPアドレスを表示します(ドメインをIPに再配置します)


-1

上記のソリューションに加えて、以下のスクリプトを使用して複数のホスト名をipに変換できます。唯一の依存関係は、コアUnixの「ping」コマンドです。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.