Hur kan jag lösa ett värdnamn till en IP-adress i ett Bash-skript?

Vad är det mest kortfattade sättet att lösa ett värdnamn till en IP-adress i ett Bash-skript? Jag använder Arch Linux .

Kommentarer

  • Skäm att getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname> svarar är någonstans där nere vid botten. Det ’ är det enklaste, kräver inga extra paket och är enklare att analysera från ett Bash-skript också.
  • @ 0xC0000022L: Den nya skam är att det svaret antyder getent hosts somehost, när kör den här medan den är på somehost producerar en IPv6-adress , som skiljer sig från hur de flesta andra verktyg (ping, ssh åtminstone) lösa namn och bryta några saker. Använd ahosts istället för hosts.
  • @j_random_hacker: som hindrar dig från att begära specifikt IPv4 (ahostsv4) eller IPv6 (ahostsv6) adresser? Personligen finner jag inget fel med att den ospecifika begäran om att returnera IPv6. Din kod bör förberedas. IPv6 har funnits i mer än 20 år nu.
  • @ 0xC0000022L: Ingen ” håller mig ” från gör det, men svaret antyder specifikt hosts, och hittills har 4 personer röstat för vinc17 ’ s kommentar som uttrycker smärtan orsakad av ” plötsligt IPv6 ”. Att vara förberedd för IPv6 är inte alltid problemet: många program behöver ett sätt att avgöra om två namn / adresser hänvisar till samma värd. De kan antingen använda enkel strängmatchning eller så måste de veta mycket om nätverket för att hitta ” true ” svaret. Det senare är ett minfält, så många tredjepartsprogram och system – som jag inte har kontroll över – använder det tidigare.

Svar

Du kan använda getent, som kommer med glibc (så att du nästan säkert har det på Linux) . Detta löser sig med hjälp av gethostbyaddr / gethostbyname2, och så kommer också att kontrollera /etc/hosts / NIS / etc:

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

Eller, som Heinzi sa nedan kan du använda dig med argumentet +short (frågar DNS-servrar direkt, ser inte på /etc/hosts / NSS / etc):

dig +short unix.stackexchange.com 

Om dig +short inte är tillgänglig är någon av följande bör fungera. Alla dessa frågor DNS direkt och ignorerar andra lösningar:

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

Om du bara vill skriva ut en IP, lägg till exit -kommando till awk” s arbetsflöde.

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

Kommentarer

  • Som standard fungerar dig bara med ipv4, där värden ger både ipv4- och ipv6-svar. Detta kan vara oväntat. Du kan prova host www.google.com, dig +short www.google.com, host ipv6.google.com, dig +short ipv6.google.com, host www.facebook.com , dig +short www.facebook.com.
  • DIG fungerar inte, om det är ett CNAME kommer det inte att returnera IP-adressen.
  • Ibland host kan ta timeout och returnerar ingenting. För vissa domäner kan dig +short returnera domänalias på första raden. Så för att säkerställa att utdata är en IPv4 adress, använd dig +short example.com | grep -Eo '[0-9\.]{7,15}' | head -1.
  • Att använda getent hosts <host> är felaktigt, som för instan det kan ge en IPv6-adress medan IPv6 inte fungerar ’. Den rätta lösningen är att använda getent ahosts <host> för att prova både IPv6 och IPv4 om det behövs.
  • Värt att nämna: host, dig och nslookup verkar direkt prata med de listade servrarna i resolv.conf, medan ” getent-värdar ” respekterar både den lokala värdfilen och cachning på biblioteksnivå (t.ex. nscd) om aktiverad .

Svar

Med host från dnsutils paket:

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

( Korrigerad paketnamn enligt kommentarerna. Som en anmärkning har andra distributioner host i olika paket: Debian / Ubuntu bind9-host , openSUSE bind-utils , Frugalware bind .)

Kommentarer

  • Se resolip-posten nedan om du behöver lösa något som inte finns i DNS (t.ex. / etc / hosts)
  • Var medveten om att host returnerar ibland flerradig utdata (vid omdirigeringar), du ’ vill host unix.stackexchange.com | tail -n1 om du bara vill ha raden med IP-adressen.
  • Det finns flera versioner av ” värd ” med olika utdataformat. T.ex. de flesta system verkar ha BIND9-versionen, men min Ubuntu 10.04 LTS-server har någon helt annan version på något sätt ..
  • om du inte ’ t har host eller dig installerad kan du använda ping istället som alltid är tillgängligt: ping unix.stackexchange.com -c 1 -q 2>&1 | grep -Po "(\d{1,3}\.){3}\d{1,3}" detta behöver ingen extra paket installeras på de flesta Unix / Linux-matchiner.
  • Detta svar förtjänar en allvarlig nedröstning. host är ett DNS-verktyg (liknar nslookup) så det letar bara upp värdar i DNS, inte i t.ex. /etc/hosts. Så det är INTE ett svar på OP ’ s fråga.

Svar

Jag har ett verktyg på min maskin som verkar göra jobbet. Man-sidan visar att det verkar komma med mysql … Så här kan du använda den:

resolveip -s unix.stackexchange.com 64.34.119.12 

Returvärdet för detta verktyg skiljer sig från 0 om värdnamnet inte kan lösas:

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

UPPDATERING På fedora kommer den med 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 

Jag antar att det skulle skapa ett konstigt beroende för ditt skript …

Kommentarer

  • Detta verkar vara den enda lösningen här som använder OS ’ s inbyggda resolver – så fungerar för / etc / hosts samt DNS.
  • getent, som beskrivs i det andra svaret, tittar också på / etc / hosts och kommer med glibc, så har inga beroenden på ett Linux-system.
  • Jag skulle inte använda resolip eftersom du skapar ett beroende av ett annat paket. getent är installerat som standard. host, nslookup och dig finns alla i valfria paket. Definitivt använd getent i ett skript.
  • Jag gillar det här svaret men det ’ t returnerar ipv6

Svar

Följande kommando med dig gör att du kan läsa resultatet direkt utan sed / awk / etc. magi:

$ dig +short unix.stackexchange.com 64.34.119.12 

dig ingår också i dnsutils paket.


Obs : dig har ett returvärde på 0, även om namnet inte kunde lösas. Således måste du kontrollera om utdata är tom istället för att kontrollera returvärdet:

hostname=unix.stackexchange.com ip=`dig +short $hostname` if [ -n "$ip" ]; then echo IP: $ip else echo Could not resolve hostname. fi 

Anmärkning 2 : Om ett värdnamn har flera IP-adresser (försök till exempel debian.org) returnerade. Detta ”problem” påverkar alla de verktyg som nämns i den här frågan hittills:

Kommentarer

  • Observera att om en domän har en CNAME-post domänen kan skrivas ut på första raden istället för en IP-adress.

Svar

getent hosts unix.stackexchange.com | cut -d" " -f1 

Kommentarer

  • Tänk också på ahosts, ahostsv4, ahostsv6 med getent.
  • cut kommer inte att getent ’ s, som använder \t för att separera kolumner. Så är fallet på Solaris.
  • @ceving: På Sola ris kan du behöva köra cut utan -d (standard är \t som avgränsare). På Linux är det ’ s mellanslag, därmed fungerar raden ovan.

Svar

De hittills givna lösningarna fungerar mest i det enklare fallet: värdnamnet löses direkt till en enda IPv4-adress. Det här kan vara det enda fallet där du behöver lösa värdnamn, men om inte, nedan är en diskussion om några fall som du kan behöva hantera.

Chris Down och Heinzi diskuterade kort fallet där värdnamnet löser sig till mer än en IP-adress. I det här fallet (och andra nedan) kan grundläggande skript under antagandet att ett värdnamn direkt löses till en enda IP-adress bryta. Nedan följer ett exempel med ett värdnamn som löser mer än en enda IP-adress:

$ 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 

Men vad är www.l.google.com ? Det är här alias fallet måste införas. Låt oss kontrollera exemplet nedan:

$ 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 löser sig inte direkt till IP-adresser utan till ett alias som i sig löser flera IP-adresser. För mer information om alias, se här . Det är naturligtvis möjligt att ett alias har en enda IP-adress , som visas nedan:

$ 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 

Men kan alias kedjas?Svaret är 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 

Jag hittade inget exempel där ett värdnamn löser sig till ett alias som inte löser sig till en IP-adress, men jag tror att fall kan uppstå.

Mer än flera IP-adresser och alias, finns det några andra speciella fall … hur är det med IPv6? Du kan försöka:

$ 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 

Där värdnamnet ipv6.google.com är ett IPv6-endast värdnamn. Vad sägs om dubbla stack-värdnamn:

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

Återigen om IPv6, om din värd endast är IPv4, kan du fortfarande lösa IPv6-adresser (testad på en IPv4-WinXP bara och med ipv6.google.com kan du prova det på Linux). I det här fallet lyckas upplösningen, men en ping misslyckas med ett okänt värdfelmeddelande . Det här kan vara ett fall där ditt skript misslyckas.

Jag hoppas att dessa kommentarer var användbara.

Kommentarer

  • Vilket fantastiskt komplement till det accepterade svaret och visar alla kantfall som man kanske vill hantera i skript. Min version host anger inte ens ” har adressen ” för mina rutor.

Svar

För att undvika problemet med alias och alltid få en enda IP-adress redo att användas:

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

Kommentarer

Svar

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

fungerar utan beroende av andra system (och för värdar som anges i / etc / hosts)

Kommentarer

  • Användningen av ping är vad jag behövde eftersom jag behöver värdet från värdfilen men sedmönstret parsas korrekt men det fungerade ping – q -c 1 -t 1 your_host_here | grep PING | sed -e ” s / ^ [^ (] * [(] // ” | sed -e ” s / [)]. * $ // ”
  • För att lösa något i mitt hemnätverk som mitt värdnamn. lokal fungerar det så för mig detta är det bästa svaret.
  • Får jag också föreslå detta: ping -q -c 1 -t 1 bahface.local | grep -m 1 PING | cut -d "(" -f2 | cut -d ")" -f1
  • getent <ahosts|ahostsv4|ahostsv6|hosts> <hostname> fungerar för deklarationer inuti /etc/hosts också … och det ’ är verktyget för alla typer av systemdatabaser (passwd, grupp, alias, tjänster).

Svar

Enkelt men användbart :

  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

Alla kommandon kommer att lösa en IP-adress om värden fortfarande finns. Om värden pekar på ett CNAME får den också IP-adressen i det fall.

Det första kommandot returnerar den lösta IPv4-adressen.

Det andra kommandot returnerar res olved IPv6-adress.

Det tredje kommandot returnerar ägarens föredragna adress, som antingen kan vara en IPv4- eller en IPv6-adress.

Kommentarer

  • Den överlägset enklaste. Och det är tillgängligt som standard. Inte som host som kräver installation av bindutils

Svar

Här är en liten variation av ping tillvägagångssätt som tar hänsyn till ”okänd värd” (genom piping genom stderr) och använder tr för att undvika användning av sed regexps:

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

Om det är viktigt att fånga utgångsvärdet, då fungerar följande (även om det är mindre 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}" 

Kommentarer

  • Jag älskar den här lösningen, eftersom den fungerar utan några extra verktyg.

Svar

För att slutföra Chris Downs svar och adressera jfgagne-kommentarer om (eventuellt kedjade) alias, här är en lösning som:

  • tar hänsyn till flera IP-adresser
  • tar hänsyn till ett eller flera alias (CNAME)
  • frågar inte /etc/hosts -fil ( i mitt fall ville jag inte det); för att fråga det är dbernt ”s pythonlösning perfekt)
  • använder inte awk / sed

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

Returnerar alltid den första IP-adressen, eller tom tring om den inte löses. med version av dig:

 $ dig -v DiG 9.8.1-P1 

Kommentarer

  • Tack, andra svar antar att ” dig + kort ” alltid returnerar en enda IP-adress. De ’ t redovisade CNAME.

Svar

 php -r "echo gethostbyname("unix.stackexchange.com");" 

Kommentarer

  • detta fungerar, men det kräver att php är installerat på din terminal
  • kan vara användbart i en typisk php-dockningsbehållare där ” värd ”, ” dig ” etc. är inte tillgängliga

Svar

Jag skulle vilja lägga till detta som en kommentar till Andrew McGregor Re: ping. Men det skulle inte låta mig, så jag måste lägga till detta som ett annat svar. (Om någon kan flytta det till en kommentar är du välkommen att göra det.)

Detta är en annan variant, bara med ping och grep :

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

grep -E för utökat reguljärt uttryck och grep -o till returnera endast matchande del. regex själv söker efter en eller flera siffror ([0-9]+) och valfritt en punkt (\.?) fyra gånger ( {4})

Svar

Du kan använda 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 

Svara

här ”ett Bash-recept Jag kokade upp med andra folks svar – försök först /etc/hosts och faller sedan tillbaka till 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 }  

Kommentarer

  • För att vara tydlig är getent hosts ’ t bara en uppslagning i / etc / hosts – det ’ ett fullständigt DNS-upplösande samtal till gethostbyaddr (3) , och det ’ s mycket osannolikt att det misslyckas i ett fall där dig kommer att lyckas. Se man-sidan för getent .
  • @Stuart har rätt – jag ’ har lärt mig mycket sedan jag skrev det och förenklat ett kraftfullt kommando. getent förblir min favorit, även om jag också gillar dig +short

Svar

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

var lösningen jag hittade utan DNS-server

Svar

Kanske inte det mest kortfattade, men det verkar vara robust och effektivt:

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

Detta ger en enda IPv4 IP, samt returnera 1 i händelse av fel, medan du maskerar stderr-utdata.

Du kan använda den så här:

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 

Googles IP är 216.58.192.46.

Om du istället vill ha en IPv6-adress, byt bara ut -4 med -6.

Svar

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

Kommentarer

  • Något sammanhang på vilket sätt det svaret förbättras jämfört med det som redan finns vara bra. Vänligen dra också in kommandon med fyra blanksteg (se syntax för markdown).

Svar

dig är också långsam, nslookup är mycket snabbare

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

Svar

1 rad löser en lista av värdnamn

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

Svar

Jag gör det hela tiden på min Mac som inte har getent. ping verkar som ett hack. Jag vill också ta med /etc/hosts.

Så jag skrev ett dumt omslag för dns.lookup för du som har Node.js installerad för att tillhandahålla en CLI:

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

Kommentarer

  • 60% chans innan du kommer nära en lösning.
  • @dotbit kan du utarbeta? Jag ’ har använt det här varje vecka sedan ’ 17 och aldrig haft några problem.
  • @Jensen men du ’ är den enda någonsin, som alltid. Resten av oss stöter vanligtvis på FAIL av det ena eller det andra, och alltid.
  • ” som alltid ” Vad menar du med det? ” Vi andra ” Vem ’ är det ? ” stöter på FAIL ” Vilken specifik fråga ser du? Jag ’ är nyfiken.

Svar

Jag don ” vet inte det enklaste sättet för ett bash-skript men om du vill lösa ett värdnamn och se om värden är uppe, använd ping!

ping -a hostname -c 1 

Kommer ping värden en gång och löser värdnamnet till IP-adress.

$ 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 

Kommentarer

  • att använda ping är bra, för alla har det, men du måste filtrera IP-delen från utgångarna, om du vill använda den i ett skript.

Svar

Ja, det finns redan många svar, men en lösning med perl saknas:

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

I ett bash-skript kan det användas så här:

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

Moduler som används här är kärnmoduler, så de bör vara tillgängliga överallt utan installation med CPAN.

Kommentarer

  • perl -MSocket -MNet::hostent -E 'say inet_ntoa((gethost shift)->addr)' unix.stackexchange.com 2>/dev/null är mycket renare. men ingen annan än vi använder p ö rl, alla andra använder naturligtvis Pascal Script.
  • Egentligen föredrar jag att se felmeddelandena om något går fel. Can't call method "addr" on an undefined value isn ’ t exakt det bästa felmeddelandet, men kan ge en aning om problemet.

Svar

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

Kommentarer

  • Rubyversionen skriver ut citat runt IP-adressen — troligen bör print användas istället för p.
  • thx, @Slaven Rezic och rösta gärna. sedan igen, här längst ner kan manuset vara mer synligt faktiskt … 😉

Svar

host -t a cisco.com 

det här kommandot visar ip-adressen (kommer att återställa domänen till IP)

Svar

Förutom ovanstående lösning kan du översätta flera värdnamn till ip via nedanstående skript, det enda beroendet är kommandot ”ping” i Unix-kärnan:

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 

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *