risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come posso risolvere un nome host in un indirizzo IP in uno script Bash?

Qual è il modo più conciso per risolvere un nome host in un indirizzo IP in uno script Bash? Sto usando Arch Linux .

450
Eugene Yarmash

Puoi usare getent, che viene fornito con glibc (quindi quasi sicuramente ce l'hai su Linux). Questo si risolve usando gethostbyaddr/gethostbyname2 e quindi controllerà /etc/hosts/NIS/etc:

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

Oppure, come ha detto Heinzi sotto, puoi usare Dig con il +short argomento (interroga direttamente i server DNS, non guarda /etc/hosts/NSS/ecc.):

Dig +short unix.stackexchange.com

Se Dig +short non è disponibile, una delle seguenti opzioni dovrebbe funzionare. Tutti questi interrogano direttamente il DNS e ignorano altri mezzi di risoluzione:

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

Se si desidera stampare un solo IP, quindi aggiungere il comando exit al flusso di lavoro di 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

Con Host dal pacchetto dnsutils :

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

( Corretto nome del pacchetto in base ai commenti. Come nota altre distribuzioni hanno Host in diversi pacchetti: Debian/Ubuntu bind9-Host, openSUSE bind-utils, Frugalware bind.)

146
manatwork

Ho uno strumento sulla mia macchina che sembra fare il lavoro. La pagina man mostra che sembra venire con mysql ... Ecco come potresti usarlo:

resolveip -s unix.stackexchange.com
64.34.119.12

Il valore di ritorno di questo strumento è diverso da 0 se il nome host non può essere risolto:

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

UPDATE Su Fedora, viene fornito con 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

Immagino che creerebbe una strana dipendenza per la tua sceneggiatura ...

56
greg0ire

Il seguente comando usando Dig ti permette di leggere il risultato direttamente senza sed/awk/etc. Magia:

$ Dig +short unix.stackexchange.com
64.34.119.12

Dig è anche incluso nel pacchetto dnsutils.


Nota: Dig ha un valore di ritorno di 0, anche se non è stato possibile risolvere il nome. Pertanto, è necessario verificare se l'output è vuoto anziché verificare il valore restituito:

hostname=unix.stackexchange.com

ip=`Dig +short $hostname`

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

Nota 2: se un nome host ha più indirizzi IP (prova debian.org, ad esempio), verranno restituiti tutti. Questo "problema" riguarda tutti gli strumenti menzionati finora in questa domanda:

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

Le soluzioni fornite finora funzionano principalmente nel caso più semplice: il nome host si risolve direttamente in un singolo indirizzo IPv4. Questo potrebbe essere l'unico caso in cui è necessario risolvere i nomi host, ma in caso contrario, di seguito è una discussione su alcuni casi che potrebbe essere necessario gestire.

Chris Down e Heinzi hanno discusso brevemente del caso in cui il nome host si risolve in più di un indirizzo IP. In questo caso (e altri sotto), gli script di base presupponendo che un nome host si risolva direttamente in un singolo indirizzo IP potrebbero non funzionare. Di seguito, un esempio con un nome host che si risolve in più di un singolo indirizzo 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

Ma cosa è www.l.google.com? È qui che deve essere introdotto il caso alias . Controlliamo l'esempio di seguito:

$ 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

Così www.google.com non si risolve direttamente in indirizzi IP, ma in un alias che si risolve da solo in più indirizzi IP. Per ulteriori informazioni sugli alias, selezionare qui . Naturalmente, è possibile il caso in cui un alias abbia un singolo indirizzo IP, come mostrato di seguito:

$ 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

Ma gli alias possono essere concatenati? La risposta è si:

$ 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

Non ho trovato alcun esempio in cui un nome host si risolva in un alias che non si risolve in un indirizzo IP, ma penso che potrebbe verificarsi il caso.

Più di più indirizzi IP e alias, ci sono altri casi speciali ... che dire di IPv6? Puoi provare:

$ 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

Dove il nome host ipv6.google.com è un nome host solo IPv6. Che dire dei nomi host dual-stack:

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

Ancora su IPv6, se il tuo host è solo IPv4, puoi comunque risolvere gli indirizzi IPv6 (testato su un IPX solo WinXP IPv e con ipv6.google.com, puoi provarlo su Linux). In questo caso, la risoluzione ha esito positivo, ma un ping non riesce con un messaggio di errore dell'host sconosciuto. Questo potrebbe essere un caso in cui il tuo scripting non riesce.

Spero che queste osservazioni siano state utili.

30
jfg956

Per evitare il problema con gli alias e ottenere sempre un singolo indirizzo IP pronto per l'uso:

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

Semplice ma utile:

  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

Tutti i comandi risolveranno un indirizzo IP se l'host esiste ancora. Se Host punta a CNAME otterrà anche l'IP in quel caso.

Il primo comando restituisce l'indirizzo IPv4 risolto

Il secondo comando restituisce l'indirizzo IPv6 risolto

Il terzo comando restituirà l'indirizzo preferito dai proprietari quale indirizzo IPv4 o IPv6.

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

funziona senza dipendenze da altri sistemi (e per host specificati in/etc/hosts)

19
Andrew McGregor

Ecco una leggera variazione dell'approccio ping che tiene conto di "Host sconosciuto" (eseguendo il piping tramite stderr) e usa tr per evitare l'uso di sed regexps:

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

Nel caso in cui sia importante acquisire il valore di uscita, funzionerà quanto segue (sebbene meno elegante):

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

Per completare la risposta di Chris Down e rispondere ai commenti di jfgagne sugli alias (possibilmente concatenati), ecco una soluzione che:

  • tiene conto di più IP
  • prende in considerazione uno o più alias (CNAME)
  • non interroga /etc/hosts file (nel mio caso non lo volevo); per interrogarlo, dbernt's python è perfetta)
  • non usa awk/sed

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

Restituisce sempre il primo indirizzo IP, oppure vuota la stringa se non risolta. con versione di Dig:

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

Mi sarebbe piaciuto aggiungere questo come commento a Andrew McGregor Re: ping. Tuttavia non me lo permetterebbe, quindi devo aggiungere questo come un'altra risposta. (Se qualcuno può spostarlo in un commento, sentiti libero di farlo.)

Questa è un'altra variante, usando solo ping e grep:

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

grep -E per espressione regolare estesa e grep -o per restituire solo la parte corrispondente. lo stesso regexp cerca una o più cifre ([0-9]+) e facoltativamente un punto (\.?) quattro volte ({4})

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

era la soluzione che ho trovato senza server DNS

5
Philippe Gachoud

ecco una ricetta Bash che ho preparato usando le risposte di altre persone - primi tentativi /etc/hosts, quindi torna a 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

È possibile utilizzare 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

Forse non il più conciso, ma sembra essere robusto ed efficiente:

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

Questo produrrà un singolo IP IPv4, oltre a return 1 in caso di errore, mentre maschera l'output stderr.

Puoi usarlo in questo modo:

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

L'IP di Google è 216.58.192.46.

Se invece desideri un indirizzo IPv6, sostituisci semplicemente -4 con -6.

4
Will

Lo scavo è troppo lento, nslookup è molto più veloce

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 riga risolve un elenco di nomi host

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

Non conosco il modo più semplice per uno script bash ma se vuoi risolvere un nome host e vedere se l'host è attivo, usa ping!

ping -a hostname -c 1

ping l'host una volta e risolverà il nome host in indirizzo 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

Lo sto facendo continuamente sul mio Mac che non ha getent. ping sembra un trucco. Vorrei prendere /etc/hosts anche in considerazione.

Quindi, ho scritto uno stupido wrapper per dns.lookup per te su cui hai installato Node.js per fornire una CLI:

$ 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

Sì, ci sono già molte risposte, ma manca una soluzione che utilizza Perl:

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

In uno script bash potrebbe essere usato in questo modo:

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

I moduli utilizzati qui sono moduli core, quindi dovrebbero essere disponibili ovunque senza installazione con CPAN.

2
Slaven Rezic