it-swarm-eu.dev

Jak mohu vyřešit jméno hostitele na IP adresu ve skriptu Bash?

Jaký je nejkratší způsob, jak vyřešit název hostitele na IP adresu ve skriptu Bash? Používám Arch Linux .

450
Eugene Yarmash

Můžete použít getent, který je dodáván s glibc (takže ho téměř určitě máte na Linuxu). To se vyřeší pomocí gethostbyaddr/gethostbyname2, a tak také zkontrolujeme /etc/hosts/NIS/etc:

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

Nebo, jak Heinzi řekl níže, můžete použít argument Dig s argumentem +short (Dotazuje servery DNS přímo, nehledí na /etc/hosts/NSS/atd.):

Dig +short unix.stackexchange.com

Pokud Dig +short Není k dispozici, měl by fungovat některý z následujících způsobů. Všechny tyto dotazy DNS přímo a ignorovat jiné způsoby řešení:

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

Pokud chcete vytisknout pouze jednu IP, přidejte příkaz exit do pracovního postupu 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

S balíčkem Host z balíčku dnsutils :

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

( Opraven název balíčku podle komentářů. Jako další poznámky mají distribuce Host v různých balíčcích: Debian/Ubuntu bind9-Host, openSUSE bind-utils, Frugalware bind.)

146
manatwork

Na svém stroji mám nástroj, který zřejmě dělá tuto práci. Na manuálové stránce se zdá, že přichází s mysql ... Zde je návod, jak byste ji mohli použít:

resolveip -s unix.stackexchange.com
64.34.119.12

Návratová hodnota tohoto nástroje se liší od 0, pokud název hostitele nelze přeložit:

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

UPDATE Ve Fedoře je dodáván s mysql-serverem:

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

Myslím, že by to vytvořilo podivnou závislost pro váš skript ...

56
greg0ire

Následující příkaz pomocí Dig umožňuje číst výsledek přímo bez sed/awk/atd. magie:

$ Dig +short unix.stackexchange.com
64.34.119.12

Dig je také součástí balíčku dnsutils.


Poznámka: Dig má návratovou hodnotu 0, i když název nelze přeložit. Proto byste měli zkontrolovat, zda je výstup prázdný, namísto kontroly návratové hodnoty:

hostname=unix.stackexchange.com

ip=`Dig +short $hostname`

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

Poznámka 2: Pokud název hostitele má více adres IP (zkuste debian.org, například), všechny budou vráceny. Tento „problém“ ovlivňuje všechny dosud zmíněné nástroje:

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

Dosud daná řešení většinou fungují v jednodušším případě: název hostitele se přímo převede na jednu adresu IPv4. To může být jediný případ, kdy je třeba vyřešit názvy hostitelů, ale pokud ne, níže je diskuse o některých případech, které budete muset zvládnout.

Chris Down a Heinzi stručně diskutovali o případu, kdy se název hostitele převede na více než jednu IP adresu. V tomto případě (a dalších níže) může dojít ke zlomení základního skriptování za předpokladu, že se název hostitele přímo převede na jednu IP adresu. Níže je uveden příklad s názvem hostitele překládajícím více než jednu IP adresu:

$ 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

Co je ale www.l.google.com? Zde je třeba uvést případ alias . Podívejme se na příklad níže:

$ 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

Tak www.google.com se přímo nerozlišuje na IP adresy, ale na aliasy, které samy překládají na více IP adres. Další informace o aliasech najdete na zde . Samozřejmě je možný případ, kdy alias má jednu IP adresu, jak je uvedeno níže:

$ 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

Lze však přezdívky spojit? Odpověď je ano:

$ 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

Nenalezl jsem žádný příklad, kde se název hostitele převede na alias, který se neřeší na IP adresu, ale myslím, že by k tomu mohlo dojít.

Více než více IP adres a aliasů, existují nějaké další zvláštní případy ... co IPv6? Můžete zkusit:

$ 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

Kde název hostitele ipv6.google.com je název hostitele pouze pro IPv6. A co názvy hostitelů s dvojitým stackem:

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

Pokud jde o IPv6 znovu, pokud je váš hostitel pouze IPv4, můžete stále rozlišovat adresy IPv6 (testováno pouze na WinXP IPv4 as adresou ipv6.google.com, můžete to zkusit na Linuxu). V tomto případě je rozlišení úspěšné, ale ping selže s neznámá chybová zpráva hostitele. To může být případ, kdy selže skriptování.

Doufám, že tyto poznámky byly užitečné.

30
jfg956

Chcete-li se vyhnout problému s aliasy a vždy mít jednu IP adresu připravenou k použití:

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

Jednoduché, ale užitečné:

  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

Všechny příkazy vyřeší IP adresu, pokud hostitel stále existuje. Pokud hostitel odkazuje na CNAME, v tom případě také získá IP.

První příkaz vrátí vyřešenou adresu IPv4

Druhý příkaz vrátí vyřešenou adresu IPv6

Třetí příkaz vrací vlastníkům preferovanou adresu, což může být adresa IPv4 nebo IPv6.

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

funguje bez závislosti na jiných systémech (a pro hostitele uvedené v/etc/hosts)

19
Andrew McGregor

Zde je malá varianta přístupu ping, který bere v úvahu „neznámého hostitele“ (potrubím přes stderr) a používá tr, aby se zabránilo použití sed regexps:

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

V případě, že je důležité zachytit výstupní hodnotu, bude fungovat následující (i když méně elegantní):

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

Chcete-li dokončit odpověď Chris Down a odpovědět na komentáře jfgagne o (možná zřetězených) aliasech, zde je řešení, které:

  • bere v úvahu více IP adres
  • bere v úvahu jednu nebo více přezdívek (CNAME)
  • nedotáže se /etc/hosts file (v mém případě jsem to nechtěl); na dotaz, dbernt's python řešení je perfektní)
  • nepoužívá awk/sed

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

Vždy vrátí první IP adresu nebo prázdný tring, pokud není vyřešen. s verzí Dig:

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

Rád bych to přidal jako poznámku k Andrewu McGregorovi Re: ping. To by mi to však nedovolilo, a tak to musím přidat jako další odpověď. (Pokud to někdo může přesunout do komentáře, neváhejte.)

Toto je další varianta používající pouze ping a grep:

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

grep -E pro rozšířený regulární výraz a grep -o pro vrácení pouze odpovídající části. regexp sám hledá jednu nebo více číslic ([0-9]+) a volitelně tečka (\.?) čtyřikrát ({4})

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

bylo řešení, které jsem našel bez serveru DNS

5
Philippe Gachoud

tady je recept na bash, který jsem uvařil pomocí odpovědí jiných lidí - první pokusy /etc/hosts, pak klesne zpět na 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

Můžete použít 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

Možná ne nejstručnější, ale zdá se být robustní a efektivní:

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

Výsledkem bude jediná IPv4 IP, stejně jako návrat 1 v případě poruchy při maskování výstupu stderr.

Můžete to použít takto:

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 společnosti Google je 216,58,192,46.

Pokud chcete místo toho adresu IPv6, stačí nahradit -4 s -6.

4
Will

Dig je příliš pomalý, nslookup je mnohem rychlejší

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 řádek vyřeší seznam hostname

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

Nevím nejjednodušší způsob bash-skriptu, ale pokud chcete vyřešit název hostitele a zjistit, zda je hostitel nahoře, použijte ping!

ping -a hostname -c 1

Jednoho dne ping hostitele a převede jméno hostitele na IP adresu.

$ 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

Dělám to pořád na svém počítači Mac, který nemá getent. ping vypadá jako hack. Chtěl bych vzít /etc/hosts také.

Takže jsem napsal blbý obal pro dns.lookup pro vás, kteří mají Node.js nainstalované k poskytnutí 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

Ano, existuje již mnoho odpovědí, ale řešení využívající Perl chybí:

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

V bash skriptu by to mohlo být použito takto:

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

Zde používané moduly jsou základní moduly, takže by měly být dostupné všude bez instalace pomocí CPAN.

2
Slaven Rezic