it-swarm.com.de

Wie kann ich einen Hostnamen in eine IP-Adresse in einem Bash-Skript auflösen?

Was ist die prägnanteste Methode, um einen Hostnamen in eine IP-Adresse in einem Bash-Skript aufzulösen? Ich benutze Arch Linux .

450
Eugene Yarmash

Sie können getent verwenden, das mit glibc geliefert wird (Sie haben es also mit ziemlicher Sicherheit unter Linux). Dies wird mit gethostbyaddr/gethostbyname2 behoben und überprüft daher auch /etc/hosts/NIS/etc:

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

Oder, wie Heinzi weiter unten sagte, können Sie Dig mit dem Argument +short Verwenden (fragt DNS-Server direkt ab, betrachtet /etc/hosts/NSS/etc nicht):

Dig +short unix.stackexchange.com

Wenn Dig +short Nicht verfügbar ist, sollte eine der folgenden Möglichkeiten funktionieren. Alle diese fragen DNS direkt ab und ignorieren andere Auflösungsmethoden:

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

Wenn Sie nur eine IP drucken möchten, fügen Sie den Befehl exit zum Workflow von awk hinzu.

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

Mit Host aus dem dnsutils Paket:

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

( Korrigierter Paketname gemäß den Kommentaren. Als Hinweis haben andere Distributionen Host in verschiedenen Paketen: Debian/Ubuntu bind9-Host, openSUSE bind-utils, Frugalware bind.)

146
manatwork

Ich habe ein Werkzeug auf meiner Maschine, das den Job zu erledigen scheint. Die Manpage zeigt, dass es mit MySQL zu kommen scheint ... So können Sie es verwenden:

resolveip -s unix.stackexchange.com
64.34.119.12

Der Rückgabewert dieses Tools unterscheidet sich von 0, wenn der Hostname nicht aufgelöst werden kann:

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

UPDATE Unter Fedora wird ein MySQL-Server mitgeliefert:

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

Ich denke, es würde eine seltsame Abhängigkeit für Ihr Skript erzeugen ...

56
greg0ire

Mit dem folgenden Befehl mit Dig können Sie das Ergebnis direkt lesen, ohne sed/awk/etc. Magie:

$ Dig +short unix.stackexchange.com
64.34.119.12

Dig ist auch im Paket dnsutils enthalten.


Hinweis: Dig hat einen Rückgabewert von 0, auch wenn der Name nicht aufgelöst werden konnte. Daher müssen Sie überprüfen, ob die Ausgabe leer ist, anstatt den Rückgabewert zu überprüfen:

hostname=unix.stackexchange.com

ip=`Dig +short $hostname`

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

Hinweis 2: Wenn ein Hostname mehrere IP-Adressen hat (versuchen Sie debian.org, zum Beispiel), werden alle zurückgegeben. Dieses "Problem" betrifft alle bisher in dieser Frage genannten Tools:

45
Heinzi
getent hosts unix.stackexchange.com | cut -d' ' -f1
44
sborsky

Die bisher angegebenen Lösungen funktionieren meist im einfacheren Fall: Der Hostname wird direkt in eine einzelne IPv4-Adresse aufgelöst. Dies ist möglicherweise der einzige Fall, in dem Sie Hostnamen auflösen müssen. Wenn dies nicht der Fall ist, werden im Folgenden einige Fälle erläutert, die Sie möglicherweise behandeln müssen.

Chris Down und Heinzi diskutierten kurz den Fall, in dem der Hostname in mehr als eine IP-Adresse aufgelöst wird. In diesem Fall (und in anderen Fällen unten) kann die grundlegende Skripterstellung unter der Annahme, dass ein Hostname direkt in eine einzelne IP-Adresse aufgelöst wird, unterbrochen werden. Unten ein Beispiel mit einem Hostnamen, der in mehr als eine einzelne IP-Adresse aufgelöst wird:

$ 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

Aber was ist www.l.google.com? Hier muss der Fall alias eingeführt werden. Schauen wir uns das folgende Beispiel an:

$ 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

Damit www.google.com wird nicht direkt in IP-Adressen aufgelöst, sondern in einen Alias, der selbst in mehrere IP-Adressen aufgelöst wird. Weitere Informationen zu Aliasen finden Sie unter hier . Natürlich ist der Fall möglich, in dem ein Alias ​​eine einzelne IP-Adresse hat, wie unten gezeigt:

$ 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

Aber können Aliase verkettet werden? Die Antwort ist ja:

$ 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

Ich habe kein Beispiel gefunden, in dem ein Hostname in einen Alias ​​aufgelöst wird, der nicht in eine IP-Adresse aufgelöst wird, aber ich denke, der Fall könnte auftreten.

Gibt es mehr als mehrere IP-Adressen und Aliase, gibt es noch andere Sonderfälle ... was ist mit IPv6? Du könntest es versuchen:

$ 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

Wo der Hostname ipv6.google.com ist ein IPv6-Hostname. Was ist mit Dual-Stack-Hostnamen:

$ 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::

Nochmals zu IPv6: Wenn Ihr Host nur IPv4 ist, können Sie weiterhin IPv6-Adressen auflösen (getestet auf nur IPv4 WinXP und mit ipv6.google.com können Sie es unter Linux versuchen). In diesem Fall ist die Auflösung erfolgreich, aber ein Ping schlägt mit einer unbekannten Host-Fehlermeldung fehl. Dies kann ein Fall sein, in dem Ihre Skripterstellung fehlschlägt.

Ich hoffe, diese Bemerkungen waren nützlich.

30
jfg956

So vermeiden Sie das Problem mit Aliasen und halten immer eine einzelne IP-Adresse bereit:

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

Einfach aber nützlich:

  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

Alle Befehle lösen eine IP-Adresse auf, wenn der Host noch vorhanden ist. Wenn Host auf CNAME zeigt, erhält er in diesem Fall auch die IP.

Der erste Befehl gibt die aufgelöste IPv4-Adresse zurück

Der zweite Befehl gibt die aufgelöste IPv6-Adresse zurück

Der dritte Befehl gibt die bevorzugte Adresse des Besitzers zurück, möglicherweise die IPv4- oder IPv6-Adresse.

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

funktioniert ohne Abhängigkeiten von anderen Systemen (und für Hosts, die in/etc/hosts angegeben sind)

19
Andrew McGregor

Hier ist eine geringfügige Variation des ping -Ansatzes, der "unbekannter Host" berücksichtigt (durch Weiterleiten durch stderr) und tr verwendet, um die Verwendung von sed Regexps zu vermeiden:

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

Wenn es wichtig ist, den Exit-Wert zu erfassen, funktioniert Folgendes (obwohl weniger elegant):

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

Um die Antwort von Chris Down zu vervollständigen und jfgagne-Kommentare zu (möglicherweise verketteten) Aliasen zu adressieren, ist hier eine Lösung, die:

  • berücksichtigt mehrere IPs
  • berücksichtigt einen oder mehrere Aliase (CNAME)
  • fragt nicht /etc/hosts file (in meinem Fall wollte ich es nicht); um es abzufragen, dbernts python Lösung ist perfekt)
  • verwendet nicht awk/sed

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

Gibt immer die erste IP-Adresse oder eine leere Zeichenfolge zurück, wenn sie nicht behoben wurde. mit Version von Dig:

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

Ich hätte dies gerne als Kommentar zu Andrew McGregor Re: ping hinzugefügt. Allerdings würde es mich nicht lassen, also muss ich dies als eine weitere Antwort hinzufügen. (Wenn jemand es in einen Kommentar verschieben kann, zögern Sie nicht.)

Dies ist eine weitere Variante, die nur Ping und Grep verwendet:

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

grep -E für erweiterten regulären Ausdruck und grep -o, um nur den passenden Teil zurückzugeben. Der reguläre Ausdruck selbst sucht nach einer oder mehreren Ziffern ([0-9]+) und optional ein Punkt (\.?) vier Mal ({4})

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

war die Lösung, die ich ohne DNS-Server gefunden habe

5

hier ist ein Bash-Rezept, das ich mit den Antworten anderer Leute zusammengestellt habe - erste Versuche /etc/hosts, fällt dann auf nslookup zurück:

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

Sie könnten Host verwenden:

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

Vielleicht nicht das prägnanteste, aber es scheint robust und effizient zu sein:

# $(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
}

Dies gibt eine einzelne IPv4-IP aus und gibt im Fehlerfall 1 Zurück, während die stderr-Ausgabe maskiert wird.

Sie können es so verwenden:

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

Die IP-Adresse von Google lautet 216.58.192.46.

Wenn Sie stattdessen eine IPv6-Adresse wünschen, ersetzen Sie einfach -4 Durch -6.

4
Will

Dig ist zu langsam, nslookup ist viel schneller

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 Zeile eine Liste mit Hostnamen auflösen

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

Ich kenne den einfachsten Weg für ein Bash-Skript nicht, aber wenn Sie einen Hostnamen auflösen und sehen möchten, ob der Host aktiv ist, verwenden Sie ping!

ping -a hostname -c 1

Wird den Host einmal ping und den Hostnamen in IP-Adresse auflösen.

$ 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

Ich mache das die ganze Zeit auf meinem Mac, der kein getent hat. ping scheint ein Hack zu sein. Ich hätte gerne /etc/hosts auch berücksichtigen.

Also schrieb ich einen dummen Wrapper für dns.lookup für Sie, auf denen Node.js installiert ist, um eine CLI bereitzustellen:

$ 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

Ja, es gibt bereits viele Antworten, aber eine Lösung mit Perl fehlt:

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

In einem Bash-Skript könnte es folgendermaßen verwendet werden:

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

Die hier verwendeten Module sind Kernmodule und sollten daher überall verfügbar sein, ohne mit CPAN installiert zu werden.

2
Slaven Rezic